Ejemplo n.º 1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="in_content"></param>
        /// <param name="out_stream"></param>
        public void SerializeMimeContent(MimeContent in_content, Stream out_stream)
        {
            byte[] _writeHelper;

            //
            // Prepare some bytes written more than once
            //
            byte[] _boundaryBytes = ParserEncoding.GetBytes("--" + in_content.Boundary);

            //
            // Write every part into the stream
            //
            foreach (var item in in_content.Parts)
            {
                //
                // First of all write the boundary
                //
                out_stream.Write(CarriageReturnLineFeed, 0, CarriageReturnLineFeed.Length);
                out_stream.Write(_boundaryBytes, 0, _boundaryBytes.Length);
                out_stream.Write(CarriageReturnLineFeed, 0, 2);

                //
                // Write the content-type for the current element
                //
                var _builder = new StringBuilder();
                _builder.Append(String.Format("Content-Type: {0}", item.ContentType));
                if (!String.IsNullOrEmpty(item.CharSet))
                {
                    _builder.Append(String.Format("; charset={0}", item.CharSet));
                }
                _builder.Append(new char[] { '\r', '\n' });

                if (!String.IsNullOrEmpty(item.TransferEncoding))
                {
                    _builder.Append(String.Format("Content-Transfer-Encoding: {0}", item.TransferEncoding));
                    _builder.Append(new char[] { '\r', '\n' });
                }

                _builder.Append(String.Format("Content-ID: {0}", item.ContentId));

                _writeHelper = ParserEncoding.GetBytes(_builder.ToString());
                out_stream.Write(_writeHelper, 0, _writeHelper.Length);

                out_stream.Write(CarriageReturnLineFeed, 0, CarriageReturnLineFeed.Length);
                out_stream.Write(CarriageReturnLineFeed, 0, CarriageReturnLineFeed.Length);

                //
                // Write the actual content
                //
                out_stream.Write(item.Content, 0, item.Content.Length);
            }

            //
            // Write one last content boundary
            //
            out_stream.Write(CarriageReturnLineFeed, 0, CarriageReturnLineFeed.Length);
            out_stream.Write(_boundaryBytes, 0, _boundaryBytes.Length);
            out_stream.Write(EndOfPartsDelimeter, 0, EndOfPartsDelimeter.Length);
            out_stream.Write(CarriageReturnLineFeed, 0, CarriageReturnLineFeed.Length);
        }
Ejemplo n.º 2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="http_content_type"></param>
        /// <param name="binary_content"></param>
        /// <returns></returns>
        public MimeContent DeserializeMimeContent(string http_content_type, byte[] binary_content)
        {
            //
            // First of all parse the http content type
            //
            string _mimeType = null, _mimeBoundary = null, _mimeStart = null;

            ParseHttpContentTypeHeader(http_content_type, ref _mimeType, ref _mimeBoundary, ref _mimeStart);

            //
            // Create the mime-content
            //
            MimeContent _content = new MimeContent()
            {
                Boundary = _mimeBoundary
            };

            //
            // Start finding the parts in the mime message
            // Note: in MIME RFC a "--" represents the end of something
            //
            var _endBoundaryHelperNdx = 0;

            byte[] _mimeBoundaryBytes = ParserEncoding.GetBytes("--" + _mimeBoundary);
            for (int i = 0; i < binary_content.Length; i++)
            {
                if (AreArrayPartsForTextEqual(_mimeBoundaryBytes, 0, binary_content, i, _mimeBoundaryBytes.Length))
                {
                    _endBoundaryHelperNdx = i + _mimeBoundaryBytes.Length;
                    if ((_endBoundaryHelperNdx + 1) < binary_content.Length)
                    {
                        // The end of the MIME-message is the boundary followed by "--"
                        if (binary_content[_endBoundaryHelperNdx] == '-' && binary_content[_endBoundaryHelperNdx + 1] == '-')
                        {
                            break;
                        }
                    }
                    else
                    {
                        throw new ProxyException("Invalid MIME content parsed, premature End-Of-File detected!");
                    }

                    // Start reading the mime part after the boundary
                    MimePart _part = ReadMimePart(binary_content, ref i, _mimeBoundaryBytes);
                    if (_part != null)
                    {
                        _content.Parts.Add(_part);
                    }
                }
            }

            //
            // Finally return the ready-to-use object model
            //
            _content.SetAsStartPart(_mimeStart);
            return(_content);
        }
Ejemplo n.º 3
0
        public void SerializeMimeContent(MimeContent content, Stream contentStream)
        {
            byte[] WriteHelper;
            byte[] CarriageReturnLineFeed = new byte[] { (byte)'\r', (byte)'\n' };

            //
            // Prepare some bytes written more than once
            //
            byte[] BoundaryBytes = ParserEncoding.GetBytes("--" + content.Boundary);

            //
            // Write every part into the stream
            //
            foreach (var item in content.Parts)
            {
                //
                // First of all write the boundary
                //
                contentStream.Write(CarriageReturnLineFeed, 0, CarriageReturnLineFeed.Length);
                contentStream.Write(BoundaryBytes, 0, BoundaryBytes.Length);
                contentStream.Write(CarriageReturnLineFeed, 0, 2);

                //
                // Write the content-type for the current element
                //
                StringBuilder Builder = new StringBuilder();
                Builder.Append(string.Format("Content-Type: {0}", item.ContentType));
                if (!string.IsNullOrEmpty(item.CharSet))
                {
                    Builder.Append(string.Format("; charset={0}", item.CharSet));
                }
                Builder.Append(new char[] { '\r', '\n' });
                Builder.Append(string.Format("Content-Transfer-Encoding: {0}", item.TransferEncoding));
                Builder.Append(new char[] { '\r', '\n' });
                Builder.Append(string.Format("Content-Id: {0}", item.ContentId));

                WriteHelper = ParserEncoding.GetBytes(Builder.ToString());
                contentStream.Write(WriteHelper, 0, WriteHelper.Length);
                contentStream.Write(CarriageReturnLineFeed, 0, CarriageReturnLineFeed.Length);
                contentStream.Write(CarriageReturnLineFeed, 0, CarriageReturnLineFeed.Length);

                //
                // Write the actual content
                //
                contentStream.Write(item.Content, 0, item.Content.Length);
            }

            //
            // Write one last content boundary
            //
            contentStream.Write(CarriageReturnLineFeed, 0, CarriageReturnLineFeed.Length);
            contentStream.Write(BoundaryBytes, 0, BoundaryBytes.Length);
            contentStream.Write(new byte[] { 45, 45 }, 0, 2);
            contentStream.Write(CarriageReturnLineFeed, 0, CarriageReturnLineFeed.Length);
        }
Ejemplo n.º 4
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);
        }
Ejemplo n.º 5
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);
        }