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); }
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); }