Beispiel #1
0
        /// <summary>
        /// Parses mime entity from stream.
        /// </summary>
        /// <param name="stream">Data stream from where to read data.</param>
        /// <param name="toBoundary">Entity data is readed to specified boundary.</param>
        /// <returns>Returns false if last entity. Returns true for mulipart entity, if there are more entities.</returns>
        internal bool Parse(SmartStream stream,string toBoundary)
        {
            // Clear header fields
            m_pHeader.Clear();
            m_pHeaderFieldCache.Clear();

            // Parse header
            m_pHeader.Parse(stream);

            // Parse entity and child entities if any (Conent-Type: multipart/xxx...)

            // Multipart entity
            if((this.ContentType & MediaType_enum.Multipart) != 0){
                // There must be be boundary ID (rfc 1341 7.2.1  The Content-Type field for multipart entities requires one parameter,
                // "boundary", which is used to specify the encapsulation boundary.)
                string boundaryID = this.ContentType_Boundary;
                if(boundaryID == null){
                    // This is invalid message, just skip this mime entity
                }
                else{
                    // There is one or more mime entities

                    // Find first boundary start position
                    SmartStream.ReadLineAsyncOP args = new SmartStream.ReadLineAsyncOP(new byte[8000],SizeExceededAction.JunkAndThrowException);
                    stream.ReadLine(args,false);
                    if(args.Error != null){
                        throw args.Error;
                    }
                    string lineString = args.LineUtf8;

                    while(lineString != null){
                        if(lineString.StartsWith("--" + boundaryID)){
                            break;
                        }

                        stream.ReadLine(args,false);
                        if(args.Error != null){
                            throw args.Error;
                        }
                        lineString = args.LineUtf8;
                    }
                    // This is invalid entity, boundary start not found. Skip that entity.
                    if(string.IsNullOrEmpty(lineString)){
                        return false;
                    }

                    // Start parsing child entities of this entity
                    while(true){
                        // Parse and add child entity
                        MimeEntity childEntity = new MimeEntity();
                        this.ChildEntities.Add(childEntity);

                        // This is last entity, stop parsing
                        if(childEntity.Parse(stream,boundaryID) == false){
                            break;
                        }
                        // else{
                        // There are more entities, parse them
                    }

                    // This entity is child of mulipart entity.
                    // All this entity child entities are parsed,
                    // we need to move stream position to next entity start.
                    if(!string.IsNullOrEmpty(toBoundary)){
                        stream.ReadLine(args,false);
                        if(args.Error != null){
                            throw args.Error;
                        }
                        lineString = args.LineUtf8;

                        while(lineString != null){
                            if(lineString.StartsWith("--" + toBoundary)){
                                break;
                            }

                            stream.ReadLine(args,false);
                            if(args.Error != null){
                                throw args.Error;
                            }
                            lineString = args.LineUtf8;
                        }

                        // Invalid boundary end, there can't be more entities
                        if(string.IsNullOrEmpty(lineString)){
                            return false;
                        }

                        // See if last boundary or there is more. Last boundary ends with --
                        if(lineString.EndsWith(toBoundary + "--")){
                            return false;
                        }
                        // else{
                        // There are more entities
                        return true;
                    }
                }
            }
            // Singlepart entity.
            else{
                // Boundary is specified, read data to specified boundary.
                if(!string.IsNullOrEmpty(toBoundary)){
                    MemoryStream entityData = new MemoryStream();
                    SmartStream.ReadLineAsyncOP readLineOP = new SmartStream.ReadLineAsyncOP(new byte[32000],SizeExceededAction.JunkAndThrowException);

                    // Read entity data while get boundary end tag --boundaryID-- or EOS.
                    while(true){
                        stream.ReadLine(readLineOP,false);
                        if(readLineOP.Error != null){
                            throw readLineOP.Error;
                        }
                        // End of stream reached. Normally we should get boundary end tag --boundaryID--, but some x mailers won't add it, so
                        // if we reach EOS, consider boundary closed.
                        if(readLineOP.BytesInBuffer == 0){
                            // Just return data what was readed.
                            m_EncodedData = entityData.ToArray();
                            return false;
                        }
                        // We readed a line.
                        else{
                            // We have boundary start/end tag or just "--" at the beginning of line.
                            if(readLineOP.LineBytesInBuffer >= 2 && readLineOP.Buffer[0] == '-' && readLineOP.Buffer[1] == '-'){
                                string lineString = readLineOP.LineUtf8;
                                // We have boundary end tag, no more boundaries.
                                if(lineString == "--" + toBoundary + "--"){
                                    m_EncodedData = entityData.ToArray();
                                    return false;
                                }
                                // We have new boundary start.
                                else if(lineString == "--" + toBoundary){
                                    m_EncodedData = entityData.ToArray();
                                    return true;
                                }
                                else{
                                    // Just skip
                                }
                            }

                            // Write readed line.
                            entityData.Write(readLineOP.Buffer,0,readLineOP.BytesInBuffer);
                        }
                    }
                }
                // Boundary isn't specified, read data to the stream end.
                else{
                    MemoryStream ms = new MemoryStream();
                    stream.ReadAll(ms);
                    m_EncodedData = ms.ToArray();
                }
            }

            return false;
        }