Example #1
0
        private MimePart ReadMimePart(byte[] binary_content, ref int current_index, byte[] mime_boundary_bytes)
        {
            byte[] _contentTypeKeyBytes      = ParserEncoding.GetBytes("Content-Type:");
            byte[] _transferEncodingKeyBytes = ParserEncoding.GetBytes("Content-Transfer-Encoding:");
            byte[] _contentIdKeyBytes        = ParserEncoding.GetBytes("Content-ID:");

            //
            // Find the appropriate content header indexes
            //
            int _contentTypeNdx = -1, _transferEncodingNdx = -1, _contentIdNdx = -1;
            int _contentTypeLen = -1, _transferEncodingLen = -1, _contentIdLen = -1;

            while (current_index < binary_content.Length)
            {
                // Try compare for keys
                if (_contentTypeNdx < 0)
                {
                    if (AreArrayPartsForTextEqual(_contentTypeKeyBytes, 0, binary_content, current_index, _contentTypeKeyBytes.Length) == true)
                    {
                        _contentTypeNdx = current_index;
                        _contentTypeLen = this.GetLengthToCRLF(binary_content, _contentTypeNdx + _contentTypeKeyBytes.Length);
                    }
                }

                if (_transferEncodingNdx < 0)
                {
                    if (AreArrayPartsForTextEqual(_transferEncodingKeyBytes, 0, binary_content, current_index, _transferEncodingKeyBytes.Length) == true)
                    {
                        _transferEncodingNdx = current_index;
                        _transferEncodingLen = this.GetLengthToCRLF(binary_content, _transferEncodingNdx + _transferEncodingKeyBytes.Length);
                    }
                }

                if (_contentIdNdx < 0)
                {
                    if (AreArrayPartsForTextEqual(_contentIdKeyBytes, 0, binary_content, current_index, _contentIdKeyBytes.Length) == true)
                    {
                        _contentIdNdx = current_index;
                        _contentIdLen = this.GetLengthToCRLF(binary_content, _contentIdNdx + _contentIdKeyBytes.Length);
                    }
                }

                // All content headers found, last content header split by Carriage Return Line Feed
                // TODO: Check index out of bounds!
                if (binary_content[current_index] == 13 && binary_content[current_index + 1] == 10)
                {
                    if (binary_content[current_index + 2] == 13 && binary_content[current_index + 3] == 10)
                    {
                        break;
                    }
                }

                // Next array index
                current_index++;
            }

            // After the last content header, we have \r\n\r\n, always
            current_index += 4;

            //
            // If not all indices found, error
            //
            //if (!((_contentTypeNdx >= 0) && (_transferEncodingNdx >= 0) && (_contentIdNdx >= 0)))
            //{
            //    // A '0' at the end of the message indicates that the previous part was the last one
            //    if (binary_content[current_index - 1] == 0)
            //        return null;
            //    else if (binary_content[current_index - 2] == 13 && binary_content[current_index - 1] == 10)
            //        return null;
            //    else
            //        throw new ProxyException("Invalid mime content passed into mime parser! Content-Type, Content-Transfer-Encoding or ContentId headers for mime part are missing!");
            //}

            //
            // Convert the content header information into strings
            //
            var _contentType = "";
            var _charSet     = "";

            if (_contentTypeNdx > 0)
            {
                _contentType = ParserEncoding.GetString(binary_content, _contentTypeNdx + _contentTypeKeyBytes.Length, _contentTypeLen).Trim();

                if (_contentType.Contains(';'))
                {
                    var _contentTypeSplitIdx = _contentType.IndexOf(';');
                    var _equalsCharSetNdx    = _contentType.IndexOf('=', _contentTypeSplitIdx + 1);

                    if (_equalsCharSetNdx < 0)
                    {
                        _charSet = _contentType.Substring(_contentTypeSplitIdx + 1).Trim();
                    }
                    else
                    {
                        _charSet = _contentType.Substring(_equalsCharSetNdx + 1).Trim();
                    }

                    _contentType = _contentType.Substring(0, _contentTypeSplitIdx).Trim();
                }
            }

            var _transferEncoding = "";

            if (_transferEncodingNdx > 0)
            {
                _transferEncoding = ParserEncoding.GetString(binary_content, _transferEncodingNdx + _transferEncodingKeyBytes.Length, _transferEncodingLen).Trim();
            }

            var _contentId = "";

            if (_contentIdNdx > 0)
            {
                _contentId = ParserEncoding.GetString(binary_content, _contentIdNdx + _contentIdKeyBytes.Length, _contentIdLen).Trim();
            }

            //
            // Current mime content starts now, therefore find the end
            //
            var _startContentIndex = current_index;
            var _endContentIndex   = -1;

            while (current_index < binary_content.Length)
            {
                if (AreArrayPartsForTextEqual(mime_boundary_bytes, 0, binary_content, current_index, mime_boundary_bytes.Length))
                {
                    _endContentIndex = current_index - 1;
                    break;
                }

                current_index++;
            }
            if (_endContentIndex == -1)
            {
                _endContentIndex = current_index - 1;
            }

            //
            // Tweak start- and end-indexes, cut all Carriage Return Line Feeds
            //
            while (true)
            {
                if ((binary_content[_startContentIndex] == 13) && (binary_content[_startContentIndex + 1] == 10))
                {
                    _startContentIndex += 2;
                }
                else
                {
                    break;
                }

                if (_startContentIndex > binary_content.Length)
                {
                    throw new ProxyException("Error in content, start index cannot go beyond overall content array!");
                }
            }

            while (true)
            {
                if ((binary_content[_endContentIndex - 1] == 13) && (binary_content[_endContentIndex] == 10))
                {
                    _endContentIndex -= 2;
                }
                else
                {
                    break;
                }

                if (_endContentIndex < 0)
                {
                    throw new ProxyException("Error in content, end content index cannot go beyond smallest index of content array!");
                }
            }

            //
            // Now create a byte array for the current mime-part content
            //
            MimePart _mimePart = new MimePart()
            {
                ContentId        = _contentId,
                TransferEncoding = _transferEncoding,
                ContentType      = _contentType,
                CharSet          = _charSet,
                Content          = new byte[_endContentIndex - _startContentIndex + 1]
            };

            Array.Copy(binary_content, _startContentIndex, _mimePart.Content, 0, _mimePart.Content.Length);

            // Go to the last sign before the next boundary starts
            current_index--;

            return(_mimePart);
        }
Example #2
0
        private MimePart ReadMimePart(byte[] binaryContent, ref int currentIndex, byte[] mimeBoundaryBytes)
        {
            byte[] ContentTypeKeyBytes      = ParserEncoding.GetBytes("Content-Type:");
            byte[] TransferEncodingKeyBytes = ParserEncoding.GetBytes("Content-Transfer-Encoding:");
            byte[] ContentIdKeyBytes        = ParserEncoding.GetBytes("Content-Id:");

            //
            // Find the appropriate content header indexes
            //
            int ContentTypeIdx = -1, TransferEncodingIdx = -1, ContentIdIdx = -1;

            while (currentIndex < binaryContent.Length)
            {
                // Try compare for keys
                if ((ContentTypeIdx < 0) && AreArrayPartsForTextEqual(ContentTypeKeyBytes, 0, binaryContent, currentIndex, ContentTypeKeyBytes.Length))
                {
                    ContentTypeIdx = currentIndex;
                }
                else if ((TransferEncodingIdx < 0) && AreArrayPartsForTextEqual(TransferEncodingKeyBytes, 0, binaryContent, currentIndex, TransferEncodingKeyBytes.Length))
                {
                    TransferEncodingIdx = currentIndex;
                }
                else if ((ContentIdIdx < 0) && AreArrayPartsForTextEqual(ContentIdKeyBytes, 0, binaryContent, currentIndex, ContentIdKeyBytes.Length))
                {
                    ContentIdIdx = currentIndex;
                }

                // All content headers found, last content header split by Carriage Return Line Feed
                // TODO: Check index out of bounds!
                if (binaryContent[currentIndex] == 13 && binaryContent[currentIndex + 1] == 10 && binaryContent[currentIndex + 2] == 13 && binaryContent[currentIndex + 3] == 10)
                {
                    break;
                }

                // Next array index
                currentIndex++;
            }

            // After the last content header, we have \r\n\r\n, always
            currentIndex += 4;

            //
            // If not all indices found, error
            //
            if (!((ContentIdIdx >= 0) && (ContentTypeIdx >= 0) && (ContentIdIdx >= 0)))
            {
                // A '0' at the end of the message indicates that the previous part was the last one
                if (binaryContent[currentIndex - 1] == 0)
                {
                    return(null);
                }
                else if (binaryContent[currentIndex - 2] == 13 && binaryContent[currentIndex - 1] == 10)
                {
                    return(null);
                }
                else
                {
                    throw new ApplicationException("Invalid mime content passed into mime parser! Content-Type, Content-Transfer-Encoding or ContentId headers for mime part are missing!");
                }
            }

            //
            // Convert the content header information into strings
            //
            string ContentType = ParserEncoding.GetString(binaryContent, ContentTypeIdx + ContentTypeKeyBytes.Length, TransferEncodingIdx - (ContentTypeIdx + ContentTypeKeyBytes.Length)).TrimStart().TrimEnd();
            string CharSet     = string.Empty;

            if (ContentType.Contains(';'))
            {
                int ContentTypeSplitIdx = ContentType.IndexOf(';');
                int EqualsCharSetIdx    = ContentType.IndexOf('=', ContentTypeSplitIdx + 1);
                if (EqualsCharSetIdx < 0)
                {
                    CharSet = ContentType.Substring(ContentTypeSplitIdx + 1).TrimStart().TrimEnd();
                }
                else
                {
                    CharSet = ContentType.Substring(EqualsCharSetIdx + 1).TrimStart().TrimEnd();
                }
                ContentType = ContentType.Substring(0, ContentTypeSplitIdx).TrimStart().TrimEnd();
            }
            string TransferEncoding = ParserEncoding.GetString(binaryContent, TransferEncodingIdx + TransferEncodingKeyBytes.Length, ContentIdIdx - (TransferEncodingIdx + TransferEncodingKeyBytes.Length)).TrimStart().TrimEnd();
            string ContentId        = ParserEncoding.GetString(binaryContent, ContentIdIdx + ContentIdKeyBytes.Length, currentIndex - (ContentIdIdx + ContentIdKeyBytes.Length)).TrimStart().TrimEnd();

            //
            // Current mime content starts now, therefore find the end
            //
            int StartContentIndex = currentIndex;
            int EndContentIndex   = -1;

            while (currentIndex < binaryContent.Length)
            {
                if (AreArrayPartsForTextEqual(mimeBoundaryBytes, 0, binaryContent, currentIndex, mimeBoundaryBytes.Length))
                {
                    EndContentIndex = currentIndex - 1;
                    break;
                }
                currentIndex++;
            }
            if (EndContentIndex == -1)
            {
                EndContentIndex = currentIndex - 1;
            }

            //
            // Tweak start- and end-indexes, cut all Carriage Return Line Feeds
            //
            while (true)
            {
                if ((binaryContent[StartContentIndex] == 13) && (binaryContent[StartContentIndex + 1] == 10))
                {
                    StartContentIndex += 2;
                }
                else
                {
                    break;
                }

                if (StartContentIndex > binaryContent.Length)
                {
                    throw new ApplicationException("Error in content, start index cannot go beyond overall content array!");
                }
            }
            while (true)
            {
                if ((binaryContent[EndContentIndex - 1] == 13) && (binaryContent[EndContentIndex] == 10))
                {
                    EndContentIndex -= 2;
                }
                else
                {
                    break;
                }

                if (EndContentIndex < 0)
                {
                    throw new ApplicationException("Error in content, end content index cannot go beyond smallest index of content array!");
                }
            }

            //
            // Now create a byte array for the current mime-part content
            //
            MimePart Part = new MimePart()
            {
                ContentId        = ContentId,
                TransferEncoding = TransferEncoding,
                ContentType      = ContentType,
                CharSet          = CharSet,
                Content          = new byte[EndContentIndex - StartContentIndex + 1]
            };

            Array.Copy(binaryContent, StartContentIndex, Part.Content, 0, Part.Content.Length);

            // Go to the last sign before the next boundary starts
            currentIndex--;

            return(Part);
        }