Esempio n. 1
0
        async Task MultipartScanSubpartsAsync(Multipart multipart, int depth, CancellationToken cancellationToken)
        {
            //var beginOffset = GetOffset (inputIndex);

            do
            {
                //OnMultipartBoundaryBegin (multipart, beginOffset);

                // skip over the boundary marker
                if (!await SkipLineAsync(true, cancellationToken).ConfigureAwait(false))
                {
                    //OnMultipartBoundaryEnd (multipart, GetOffset (inputIndex));
                    boundary = BoundaryType.Eos;
                    return;
                }

                //OnMultipartBoundaryEnd (multipart, GetOffset (inputIndex));

                var beginLineNumber = lineNumber;

                // parse the headers
                state = MimeParserState.Headers;
                if (await StepAsync(cancellationToken).ConfigureAwait(false) == MimeParserState.Error)
                {
                    boundary = BoundaryType.Eos;
                    return;
                }

                if (state == MimeParserState.Boundary)
                {
                    if (headers.Count == 0)
                    {
                        if (boundary == BoundaryType.ImmediateBoundary)
                        {
                            //beginOffset = GetOffset (inputIndex);
                            continue;
                        }
                        return;
                    }

                    // This part has no content, but that will be handled in ConstructMultipartAsync()
                    // or ConstructMimePartAsync().
                }

                //if (state == ParserState.Complete && headers.Count == 0)
                //	return BoundaryType.EndBoundary;

                var type       = GetContentType(multipart.ContentType);
                var entity     = options.CreateEntity(type, headers, false, depth);
                var entityArgs = new MimeEntityEndEventArgs(entity, multipart)
                {
                    HeadersEndOffset = headerBlockEnd,
                    BeginOffset      = headerBlockBegin,
                    LineNumber       = beginLineNumber
                };

                OnMimeEntityBegin(entityArgs);

                if (entity is Multipart)
                {
                    await ConstructMultipartAsync((Multipart)entity, entityArgs, depth + 1, cancellationToken).ConfigureAwait(false);
                }
                else if (entity is MessagePart)
                {
                    await ConstructMessagePartAsync((MessagePart)entity, entityArgs, depth + 1, cancellationToken).ConfigureAwait(false);
                }
                else
                {
                    await ConstructMimePartAsync((MimePart)entity, entityArgs, cancellationToken).ConfigureAwait(false);
                }

                var endOffset = GetEndOffset(inputIndex);
                entityArgs.HeadersEndOffset = Math.Min(entityArgs.HeadersEndOffset, endOffset);
                entityArgs.EndOffset        = endOffset;

                OnMimeEntityEnd(entityArgs);

                //beginOffset = endOffset;
                multipart.Add(entity);
            } while (boundary == BoundaryType.ImmediateBoundary);
        }
Esempio n. 2
0
        async Task ConstructMultipartAsync(Multipart multipart, MimeEntityEndEventArgs args, int depth, CancellationToken cancellationToken)
        {
            var  beginOffset     = GetOffset(inputIndex);
            var  beginLineNumber = lineNumber;
            var  marker          = multipart.Boundary;
            long endOffset;

            if (marker == null)
            {
#if DEBUG
                Debug.WriteLine("Multipart without a boundary encountered!");
#endif

                // Note: this will scan all content into the preamble...
                await MultipartScanPreambleAsync(multipart, cancellationToken).ConfigureAwait(false);

                endOffset  = GetEndOffset(inputIndex);
                args.Lines = GetLineCount(beginLineNumber, beginOffset, endOffset);
                return;
            }

            PushBoundary(marker);

            await MultipartScanPreambleAsync(multipart, cancellationToken).ConfigureAwait(false);

            if (boundary == BoundaryType.ImmediateBoundary)
            {
                await MultipartScanSubpartsAsync(multipart, depth, cancellationToken).ConfigureAwait(false);
            }

            if (boundary == BoundaryType.ImmediateEndBoundary)
            {
                //OnMultipartEndBoundaryBegin (multipart, GetEndOffset (inputIndex));

                // consume the end boundary and read the epilogue (if there is one)
                multipart.WriteEndBoundary = true;
                await SkipLineAsync(false, cancellationToken).ConfigureAwait(false);

                PopBoundary();

                //OnMultipartEndBoundaryEnd (multipart, GetOffset (inputIndex));

                await MultipartScanEpilogueAsync(multipart, cancellationToken).ConfigureAwait(false);

                endOffset  = GetEndOffset(inputIndex);
                args.Lines = GetLineCount(beginLineNumber, beginOffset, endOffset);
                return;
            }

            endOffset  = GetEndOffset(inputIndex);
            args.Lines = GetLineCount(beginLineNumber, beginOffset, endOffset);

            multipart.WriteEndBoundary = false;

            // We either found the end of the stream or we found a parent's boundary
            PopBoundary();

            unsafe
            {
                fixed(byte *inbuf = input)
                {
                    if (boundary == BoundaryType.ParentEndBoundary && FoundImmediateBoundary(inbuf, true))
                    {
                        boundary = BoundaryType.ImmediateEndBoundary;
                    }
                    else if (boundary == BoundaryType.ParentBoundary && FoundImmediateBoundary(inbuf, false))
                    {
                        boundary = BoundaryType.ImmediateBoundary;
                    }
                }
            }
        }
Esempio n. 3
0
        async Task ConstructMessagePartAsync(MessagePart rfc822, MimeEntityEndEventArgs args, int depth, CancellationToken cancellationToken)
        {
            var beginOffset     = GetOffset(inputIndex);
            var beginLineNumber = lineNumber;

            if (bounds.Count > 0)
            {
                int atleast = Math.Max(ReadAheadSize, GetMaxBoundaryLength());

                if (await ReadAheadAsync(atleast, 0, cancellationToken).ConfigureAwait(false) <= 0)
                {
                    boundary = BoundaryType.Eos;
                    return;
                }

                unsafe
                {
                    fixed(byte *inbuf = input)
                    {
                        byte *start = inbuf + inputIndex;
                        byte *inend = inbuf + inputEnd;
                        byte *inptr = start;

                        *inend = (byte)'\n';

                        while (*inptr != (byte)'\n')
                        {
                            inptr++;
                        }

                        boundary = CheckBoundary(inputIndex, start, (int)(inptr - start));

                        switch (boundary)
                        {
                        case BoundaryType.ImmediateEndBoundary:
                        case BoundaryType.ImmediateBoundary:
                        case BoundaryType.ParentBoundary:
                            return;

                        case BoundaryType.ParentEndBoundary:
                            // ignore "From " boundaries, broken mailers tend to include these...
                            if (!IsMboxMarker(start))
                            {
                                return;
                            }
                            break;
                        }
                    }
                }
            }

            // parse the headers...
            state = MimeParserState.MessageHeaders;
            if (await StepAsync(cancellationToken).ConfigureAwait(false) == MimeParserState.Error)
            {
                // Note: this either means that StepHeaders() found the end of the stream
                // or an invalid header field name at the start of the message headers,
                // which likely means that this is not a valid MIME stream?
                boundary = BoundaryType.Eos;
                return;
            }

            var message     = new MimeMessage(options, headers, RfcComplianceMode.Loose);
            var messageArgs = new MimeMessageEndEventArgs(message, rfc822)
            {
                HeadersEndOffset = headerBlockEnd,
                BeginOffset      = headerBlockBegin,
                LineNumber       = beginLineNumber
            };

            OnMimeMessageBegin(messageArgs);

            if (preHeaderBuffer.Length > 0)
            {
                message.MboxMarker = new byte[preHeaderLength];
                Buffer.BlockCopy(preHeaderBuffer, 0, message.MboxMarker, 0, preHeaderLength);
            }

            var type       = GetContentType(null);
            var entity     = options.CreateEntity(type, headers, true, depth);
            var entityArgs = new MimeEntityEndEventArgs(entity)
            {
                HeadersEndOffset = headerBlockEnd,
                BeginOffset      = headerBlockBegin,
                LineNumber       = beginLineNumber
            };

            OnMimeEntityBegin(entityArgs);

            message.Body = entity;

            if (entity is Multipart)
            {
                await ConstructMultipartAsync((Multipart)entity, entityArgs, depth + 1, cancellationToken).ConfigureAwait(false);
            }
            else if (entity is MessagePart)
            {
                await ConstructMessagePartAsync((MessagePart)entity, entityArgs, depth + 1, cancellationToken).ConfigureAwait(false);
            }
            else
            {
                await ConstructMimePartAsync((MimePart)entity, entityArgs, cancellationToken).ConfigureAwait(false);
            }

            rfc822.Message = message;

            var endOffset = GetEndOffset(inputIndex);

            messageArgs.HeadersEndOffset = entityArgs.HeadersEndOffset = Math.Min(entityArgs.HeadersEndOffset, endOffset);
            messageArgs.EndOffset        = entityArgs.EndOffset = endOffset;

            OnMimeEntityEnd(entityArgs);
            OnMimeMessageEnd(messageArgs);

            args.Lines = GetLineCount(beginLineNumber, beginOffset, endOffset);
        }