/// <summary> /// Parses MIME header from the specified stream. /// </summary> /// <param name="stream">MIME header stream.</param> /// <exception cref="ArgumentNullException">Is raised when <b>stream</b> is null.</exception> public void Parse(SmartStream stream) { //TODO: ���� ��������� �������! �������� ����! �� ��� ���� �������� � utf8 ����� if (stream == null) { throw new ArgumentNullException("stream"); } var headers = new List <KeyValuePair <string, byte[]> >(); var currentMemStream = new MemoryStream(); SmartStream.ReadLineAsyncOP readLineOP = new SmartStream.ReadLineAsyncOP(new byte[Workaround.Definitions.MaxStreamLineLength], SizeExceededAction. ThrowException); while (true) { stream.ReadLine(readLineOP, false); if (readLineOP.Error != null) { throw readLineOP.Error; } // We reached end of stream. if (readLineOP.BytesInBuffer == 0) { if (currentMemStream.Length > 0) { AddToBinaryDict(headers, currentMemStream); } m_IsModified = false; break; } // We got blank header terminator line. if (readLineOP.LineBytesInBuffer == 0) { if (currentMemStream.Length > 0) { AddToBinaryDict(headers, currentMemStream); } m_IsModified = false; break; } string line = Encoding.UTF8.GetString(readLineOP.Buffer, 0, readLineOP.BytesInBuffer); var realBuffer = new List <byte>(); if ((line.StartsWith("From: \"") || line.StartsWith("To: \"")) && !line.EndsWith(">\r\n")) { var tmpArr = new byte[readLineOP.BytesInBuffer]; Array.Copy(readLineOP.Buffer, 0, tmpArr, 0, readLineOP.BytesInBuffer); realBuffer.AddRange(tmpArr); do { stream.ReadLine(readLineOP, false); if (readLineOP.LineBytesInBuffer == 0) { break; } line = Encoding.UTF8.GetString(readLineOP.Buffer, 0, readLineOP.BytesInBuffer); tmpArr = new byte[readLineOP.BytesInBuffer]; Array.Copy(readLineOP.Buffer, 0, tmpArr, 0, readLineOP.BytesInBuffer); realBuffer.AddRange(tmpArr); } while (!line.EndsWith(">\r\n")); if (realBuffer.Count > 0) { line = Encoding.UTF8.GetString(realBuffer.ToArray()); } } // New header field starts. if (currentMemStream.Length == 0) { currentMemStream.Write(readLineOP.Buffer, 0, readLineOP.BytesInBuffer); } // Header field continues. else if (char.IsWhiteSpace(line[0])) { currentMemStream.Write(readLineOP.Buffer, 0, readLineOP.BytesInBuffer); } // Current header field closed, new starts. else { AddToBinaryDict(headers, currentMemStream); currentMemStream = new MemoryStream(); if (realBuffer.Count > 0) { currentMemStream.Write(realBuffer.ToArray(), 0, realBuffer.Count); } else { currentMemStream.Write(readLineOP.Buffer, 0, readLineOP.BytesInBuffer); } } } //Process dictionary //Find content type var contentTypeHeader = headers .Where(x => x.Value != null) .Where(x => "content-type".Equals(x.Key, StringComparison.OrdinalIgnoreCase)) .Select(x => Encoding.UTF8.GetString(x.Value)) .SingleOrDefault(); var encoding = Encoding.UTF8; if (contentTypeHeader != null) { var mime = MIME_h_ContentType.Parse(contentTypeHeader); if (!string.IsNullOrEmpty(mime.Param_Charset)) { encoding = EncodingTools.GetEncodingByCodepageName(mime.Param_Charset) ?? Encoding.UTF8; } else { //Join headers var subjectRaw = headers .Where(x => x.Value != null) .Where(x => "subject".Equals(x.Key, StringComparison.OrdinalIgnoreCase)) .Select(x => x.Value) .SingleOrDefault(); //Try to detect hueristic encoding = subjectRaw != null?EncodingTools.DetectInputCodepage(subjectRaw) : Encoding.UTF8; } } foreach (var keyValuePair in headers) { Add(encoding.GetString(keyValuePair.Value)); } }