private void ReadFromStream(MimeStreamBuffer context) { var buffer = this.GetBuffer(); var stream = _Stream; var lastLineLength = 0; var lastLine = context.GetLastLine(); if (lastLine != null) { lastLineLength = lastLine.Length; } var filledLength = buffer.Length - lastLineLength - 1; if (stream.Position + filledLength > stream.Length) { filledLength = (Int32)(stream.Length - stream.Position); } var readLength = stream.Read(buffer, 0, filledLength); if (lastLineLength > 0) { Buffer.BlockCopy(buffer, 0, buffer, lastLineLength, readLength); Buffer.BlockCopy(lastLine, 0, buffer, 0, lastLineLength); } buffer[lastLineLength + readLength] = 10; context.Initialize(_BufferPtr, lastLineLength + readLength, readLength == 0); }
private unsafe T Parse <T>(Stream stream, T message) where T : MimeMessage { T mg = message; this.Setup(stream); try { fixed(byte *bufferPtr = this.GetBuffer()) { _BufferPtr = bufferPtr; var cx = new MimeStreamBuffer(); this.ReadHeaderAndMessageBody(mg, cx); if (this.Filter.LoadContents == true && String.IsNullOrEmpty(mg.ContentType.Boundary) == false) { var boundary = this.CreateBoundary("--" + mg.ContentType.Boundary); var content = this.ReadMimeContent(cx, boundary); mg.Contents.AddRange(content); } } } catch (InvalidMimeFormatException ex) { var rawText = this.GetRawText(stream); throw new InvalidMimeFormatException(rawText, ex.ParseText); } finally { _BufferPtr = null; } if (this.Filter.LoadMessageRawData == true) { mg.RawData = _RawData.SelectMany(el => el).ToArray(); } _RawData.Clear(); return(mg); }
private List <MimeContent> ReadMimeContent(MimeStreamBuffer context, Byte[] boundary) { List <MimeContent> l = new List <MimeContent>(); MimeContent mc = null; MimeHeaderBufferByteArray headerPointer = _HeaderBuffer; var bodyBuffer = new MimeContentByteArray(); var state = MimeContentParserState.Boundary; var boundaryResult = CheckBoundaryResult.None; var isEndOfBody = false; Byte[] childBoundary = null; Byte[] line = null; MimeStreamBuffer cx = context; mc = new MimeContent(); headerPointer.Clear(); while (true) { if (context == null) { this.ReadFromStream(cx); } context = null; while (true) { switch (state) { case MimeContentParserState.Boundary: #region { line = cx.ReadLine(); if (line.Length == 0) { continue; } this.AddToRawData(line); if (line.Length == 2 && line[0] == 13 && line[1] == 10) { continue; } bodyBuffer.AddBoundaryLine(line); if (IsEndByNewLine(line) == true) { boundaryResult = bodyBuffer.CheckBoundary(boundary); switch (boundaryResult) { case CheckBoundaryResult.None: { var lineText = this.Encoding.GetString(line); throw new InvalidMimeFormatException(lineText); } case CheckBoundaryResult.Boundary: { headerPointer.Clear(); state = MimeContentParserState.Header; } break; case CheckBoundaryResult.EndBoundary: break; default: throw new InvalidOperationException(); } } } break; #endregion case MimeContentParserState.Header: #region { headerPointer = cx.ReadHeader(headerPointer); if (headerPointer.IsEmptyNewLine() == true) { var bb = headerPointer.ToArray(); this.AddToRawData(bb); bodyBuffer.AddHeaderLine(bb); bodyBuffer.HeaderLength = bodyBuffer.Length; headerPointer.Clear(); if (mc.ContentType != null && String.IsNullOrEmpty(mc.ContentType.Boundary) == false) { childBoundary = CreateBoundary("--" + mc.ContentType.Boundary); state = MimeContentParserState.ChildContent; } else { state = MimeContentParserState.Body; } } else if (headerPointer.IsEnd == true) { var bb = headerPointer.ToArray(); this.AddToRawData(bb); //New MimeHeader var header = ParseHeader(headerPointer); mc.Headers.Add(header); headerPointer.Clear(); bodyBuffer.AddHeaderLine(bb); } } break; #endregion case MimeContentParserState.Body: #region { var bodyLine = cx.ReadBody(boundary, out boundaryResult, out isEndOfBody); bodyBuffer.AddBodyLine(bodyLine); if (boundaryResult != CheckBoundaryResult.None || isEndOfBody == true) { this.SetMimeContentBody(mc, bodyBuffer); l.Add(mc); headerPointer.Clear(); bodyBuffer.Clear(); mc = new MimeContent(); state = MimeContentParserState.Boundary; } } break; #endregion case MimeContentParserState.ChildContent: #region { var bodyLine = cx.ReadBody(childBoundary, out boundaryResult, out isEndOfBody); bodyBuffer.AddBodyLine(bodyLine); if (boundaryResult != CheckBoundaryResult.None || isEndOfBody == true) { if (bodyBuffer.Length > 0) { this.AddToRawDataWithNewline(bodyBuffer.GetBodyArray()); } mc.Contents.AddRange(ReadMimeContent(cx, childBoundary)); bodyBuffer.Clear(); state = MimeContentParserState.Body; } } break; #endregion default: throw new InvalidOperationException(); } if (cx.IsEnd() == true) { break; } if (isEndOfBody == true || boundaryResult == CheckBoundaryResult.EndBoundary) { break; } } if (isEndOfBody == true || boundaryResult == CheckBoundaryResult.EndBoundary || cx.EndOfStream == true) { break; } } if (boundaryResult == CheckBoundaryResult.EndBoundary) { this.AddToRawData(boundary); this.AddToRawData(new Byte[] { 45, 45 }); } return(l); }
private unsafe void ReadHeaderAndMessageBody(MimeMessage message, MimeStreamBuffer context) { MimeHeaderBufferByteArray headerPointer = _HeaderBuffer; var bodyBuffer = new MimeContentByteArray(); Boolean endOfHeader = false; Boolean endOfBody = false; Byte[] boundary = null; var boundaryResult = CheckBoundaryResult.None; var isEndOfBody = false; var firstLine = true; var cx = context; headerPointer.Clear(); while (true) { this.ReadFromStream(cx); while (true) { if (endOfHeader == false) { #region Header headerPointer = cx.ReadHeader(headerPointer); if (headerPointer.IsEnd == false) { break; } if (firstLine == true && headerPointer.IsOkResponseLine() == true) { firstLine = false; headerPointer.Clear(); continue; } firstLine = false; var l = Encoding.UTF8.GetString(headerPointer.ToArray()); if (endOfHeader == false && headerPointer.IsEmptyNewLine() == true) { this.AddToRawData(headerPointer.ToArray()); headerPointer.Clear(); endOfHeader = true; if (String.IsNullOrEmpty(message.ContentType.Boundary) == false && boundary == null) { boundary = CreateBoundary("--" + message.ContentType.Boundary); } continue; } if (headerPointer.IsEnd == true) { //New MimeHeader var bb = headerPointer.ToArray(); this.AddToRawData(bb); var header = ParseHeader(headerPointer); message.Headers.Add(header); headerPointer.Clear(); } #endregion } else { #region Body Byte[] bodyLine = null; bodyLine = cx.ReadBody(boundary, out boundaryResult, out isEndOfBody); bodyBuffer.AddBodyLine(bodyLine); if (boundaryResult != CheckBoundaryResult.None || isEndOfBody == true) { endOfBody = true; var bb = bodyBuffer.GetBodyArray(); if (bb.Length == 0) { break; } message.TextBeforeMimeContent = this.Encoding.GetString(bb); this.AddToRawDataWithNewline(bb); if (message.ContentType.IsText == false) { break; } this.SetMimeMessageBodyText(message, bb); break; } #endregion } if (cx.IsEnd() == true || cx.EndOfStream == true) { break; } } if (endOfBody == true || cx.EndOfStream == true) { break; } } }