Example #1
0
        private void Parse()
        {
            // transform reader to stream provider to get timestamp and frame numbers values
            var _streamProvider = this._reader.PDUStreamBasedProvider;

            this.Frames = _streamProvider.ProcessedFrames;
            if (_streamProvider.GetCurrentPDU() != null)
            {
                this.Timestamp = _streamProvider.GetCurrentPDU().FirstSeen;
            }
            else
            {
                this.InvalidReason = "could not retrieve PDU";
                this.ExportSources.Add(_streamProvider.Conversation);
                this.Valid = false;
                return;
            }

            //Console.WriteLine("FTPMsg created, frame numbers: " + string.Join(",", Frames.ToArray()));
            //if(!_streamProvider.GetCurrentPDU().Conversation.ApplicationTags.Any())
            //{
            //    this.Valid = false;
            //    this.InvalidReason = "no application tag";
            //    this.ExportSources.Add(_streamProvider.GetCurrentPDU());
            //    return;
            //}

            this.ExportSources.Add(_streamProvider.GetCurrentPDU());

            // * 7 FETCH (UID 22 RFC822.SIZE 1192 BODY[] {1192}
            // * 5 FETCH (UID 19 RFC822.SIZE 3026350 BODY[]<0> {65536}
            // 35 UID fetch 19 (UID RFC822.SIZE BODY[]<65536.65536>)
            // * 5 FETCH (UID 19 RFC822.SIZE 3026350 BODY[] <65536> {65536}
            // 36 UID fetch 19(UID RFC822.SIZE BODY[] <131072.65536>)
            // * 5 FETCH (UID 19 RFC822.SIZE 3026350 BODY[]<131072> {65536}


            var _line         = this._reader.ReadLine();
            var _splittedLine = _line.Split(' ');

            if (_splittedLine.Count() < 3)
            {
                return;
            }
            var chunkSize = 0;
            var chunk     = string.Empty;

            // this is response with whole e-mail
            if (_splittedLine[0] == "*" &&
                _splittedLine[2].IndexOf("FETCH", StringComparison.OrdinalIgnoreCase) == 0 &&
                _line.IndexOf("BODY[]", 0, StringComparison.CurrentCultureIgnoreCase) != -1)
            {
                var messageSize = 0;
                for (var i = 3; i < _splittedLine.Count(); ++i)
                {
                    if (_splittedLine[i].IndexOf(".SIZE", StringComparison.OrdinalIgnoreCase) != -1)
                    {
                        // this token contains ".SIZE", next token is message size
                        if (i < (_splittedLine.Count() - 1))
                        {
                            messageSize = Int32.Parse(_splittedLine[i + 1]);
                        }
                        Debug.WriteLine("message size: " + messageSize);
                        ++i;
                    }
                    // size of the chunk
                    if (_splittedLine[i].StartsWith("{"))
                    {
                        chunkSize = Int32.Parse(_splittedLine[i].Trim('{', '}'));
                        Debug.WriteLine("chunkSize " + chunkSize);
                    }
                }
                // read all the content
                chunk = _reader.ReadToEnd();
                // chunk is complete
                if (chunk.Length >= chunkSize)
                {
                    // trim the chunk by its announced size
                    this.MessageContent += chunk.Substring(0, chunkSize);
                    // clear the hunk
                    chunkSize = 0;
                    chunk     = string.Empty;
                }
                Debug.WriteLine("content size: " + this.MessageContent.Length);

                // message is incomplete
                while (this.MessageContent.Length < messageSize)
                {
                    // we still need some data but there are none available -> incomplete message
                    if (!this._reader.NewMessage())
                    {
                        return;
                    }

                    _line         = this._reader.ReadLine();
                    _splittedLine = _line.Split(' ');

                    // line contains to few spaces - it's either continuation of chunk or some stuff we don't want
                    if (_splittedLine.Count() < 3)
                    {
                        // there is no space, it's chunk
                        if (_line.Equals(_splittedLine[0]))
                        {
                            // continuation of data
                            chunk += _line + "\r\n" + this._reader.ReadToEnd();
                            // chunk is complete
                            if (chunk.Length >= chunkSize)
                            {
                                // trim the chunk by its announced size
                                this.MessageContent += chunk.Substring(0, chunkSize);
                                // clear the chunk
                                chunkSize = 0;
                                chunk     = string.Empty;
                            }
                            // chunk is incomplete
                            else
                            {
                                Debug.WriteLine("new chunk.Length (cont.): " + chunk.Length);
                            }
                            Debug.WriteLine("new content size (cont.): " + this.MessageContent.Length);
                            // this PDU is read, go to next one
                            continue;
                        }
                        // it's not chunk but something else - skip it
                        else
                        {
                            continue;
                        }
                    }
                    // line cotains enough spaces
                    if (_splittedLine[0] == "*" &&
                        _splittedLine[2].IndexOf("FETCH", StringComparison.OrdinalIgnoreCase) == 0 &&
                        _line.IndexOf("BODY[]", 0, StringComparison.CurrentCultureIgnoreCase) != -1)
                    {
                        var skipThis = false;
                        for (var i = 3; i < _splittedLine.Count(); ++i)
                        {
                            if (_splittedLine[i].IndexOf(".SIZE", StringComparison.OrdinalIgnoreCase) != -1)
                            {
                                // this token contains ".SIZE", next token is message size
                                if (i < (_splittedLine.Count() - 1))
                                {
                                    // announced messages size differs from previously announced one - this shouldn't be
                                    if (messageSize != Int32.Parse(_splittedLine[i + 1]))
                                    {
                                        // break inner for cycle
                                        i = _splittedLine.Count();
                                        // flag this chunk for skipping
                                        skipThis = true;
                                        continue;
                                    } //else { Debug.Print("matching size"); }
                                }
                                ++i;
                            }
                            // size of the chunk
                            if (_splittedLine[i].StartsWith("{"))
                            {
                                chunkSize = Int32.Parse(_splittedLine[i].Trim('{', '}'));
                                Debug.WriteLine("chunkSize " + chunkSize);
                            }
                        }
                        // not skipping
                        if (!skipThis)
                        {
                            chunk += _reader.ReadToEnd();
                            if (chunk.Length >= chunkSize)
                            {
                                // trim chunk by its announced size
                                this.MessageContent += chunk.Substring(0, chunkSize);
                                // clear the chunk
                                chunkSize = 0;
                                chunk     = string.Empty;
                            }
                            else
                            {
                                Debug.WriteLine("new chunk.Length: " + chunk.Length);
                            }
                            Debug.WriteLine("new content size: " + this.MessageContent.Length);
                        }
                    }
                }
                // message is complete
                this.Type = IMAPMsgType.FETCH_BODY;
            }
        }