/// <summary> /// The convert mime content. /// </summary> /// <param name="messageId"> /// The message id. /// </param> /// <param name="part"> /// The part. /// </param> /// <param name="sb"> /// The sb. /// </param> /// <param name="attachmentList"> /// The attachment list. /// </param> private void ConvertMIMEContent(string messageId, MIMEPart part, StringBuilder sb, ArrayList attachmentList) { Match m = null; m = Regex.Match(part.ContentType, @"MULTIPART", RegexOptions.IgnoreCase); if (m.Success) { foreach (MIMEPart subPart in part.EmbeddedPartList) { this.ConvertMIMEContent(messageId, subPart, sb, attachmentList); } return; } m = Regex.Match(part.ContentType, @"TEXT", RegexOptions.IgnoreCase); if (m.Success) { sb.Append(part.Text); sb.Append("<hr>"); return; } var attachment = new Attachment(messageId + " - " + part.Filename, part.Filename, part.BinaryData); attachmentList.Add(attachment); }
/// <summary> /// The get mime body. /// </summary> /// <param name="messageId"> /// The message id. /// </param> /// <param name="part"> /// The part. /// </param> /// <returns> /// </returns> private ArticleBody GetMIMEBody(string messageId, MIMEPart part) { string line = null; ArticleBody body = null; StringBuilder sb = null; var attachmentList = new ArrayList(); try { NntpUtil.DispatchMIMEContent(this.sr, part, "."); sb = new StringBuilder(); attachmentList = new ArrayList(); body = new ArticleBody { IsHtml = true }; this.ConvertMIMEContent(messageId, part, sb, attachmentList); body.Text = sb.ToString(); body.Attachments = (Attachment[])attachmentList.ToArray(typeof(Attachment)); } finally { if (((NetworkStream)this.sr.BaseStream).DataAvailable) { while ((line = this.sr.ReadLine()) != null && line != ".") { ; } } } return(body); }
public Article GetArticle(string messageId) { if (this.connectedServer == null) { throw new NntpException("No connecting newsserver."); } if (this.connectedGroup == null) { throw new NntpException("No connecting newsgroup."); } var article = new Article(); Response res = this.MakeRequest("Article " + messageId); if (res.Code != 220) { throw new NntpException(res.Code); } int i = res.Message.IndexOf(' '); article.ArticleId = int.Parse(res.Message.Substring(0, i)); int end = res.Message.Substring(i, res.Message.Length - i - 1).Trim().IndexOf(' '); if (end == -1) { end = res.Message.Length - (i + 1); } article.MessageId = res.Message.Substring(i + 1, end); MIMEPart part = null; article.Header = this.GetHeader(messageId, out part); article.MimePart = part; article.Body = article.MimePart == null?this.GetNormalBody(article.MessageId) : this.GetMIMEBody(article.MessageId, article.MimePart); return(article); }
/// <summary> /// The get mime body. /// </summary> /// <param name="messageId"> /// The message id. /// </param> /// <param name="part"> /// The part. /// </param> /// <returns> /// </returns> private ArticleBody GetMIMEBody(string messageId, MIMEPart part) { string line = null; ArticleBody body = null; StringBuilder sb = null; var attachmentList = new ArrayList(); try { NntpUtil.DispatchMIMEContent(this.sr, part, "."); sb = new StringBuilder(); attachmentList = new ArrayList(); body = new ArticleBody { IsHtml = true }; this.ConvertMIMEContent(messageId, part, sb, attachmentList); body.Text = sb.ToString(); body.Attachments = (Attachment[]) attachmentList.ToArray(typeof (Attachment)); } finally { if (((NetworkStream) this.sr.BaseStream).DataAvailable) { while ((line = this.sr.ReadLine()) != null && line != ".") { ; } } } return body; }
/// <summary> /// The get header. /// </summary> /// <param name="messageId"> /// The message id. /// </param> /// <param name="part"> /// The part. /// </param> /// <returns> /// </returns> private ArticleHeader GetHeader(string messageId, out MIMEPart part) { string response = null; var header = new ArticleHeader(); string name = null; string value = null; header.ReferenceIds = new string[0]; string[] values = null; string[] values2 = null; Match m = null; part = null; int i = -1; while ((response = this.sr.ReadLine()) != null && response != string.Empty) { m = Regex.Match(response, @"^\s+(\S+)$"); if (m.Success) { value = m.Groups[1].ToString(); } else { i = response.IndexOf(':'); if (i == -1) { continue; } name = response.Substring(0, i).ToUpper(); value = response.Substring(i + 1); } switch (name) { case "REFERENCES": values = value.Trim().Split(' '); values2 = header.ReferenceIds; header.ReferenceIds = new string[values.Length + values2.Length]; values.CopyTo(header.ReferenceIds, 0); values2.CopyTo(header.ReferenceIds, values.Length); break; case "SUBJECT": header.Subject += NntpUtil.Base64HeaderDecode(value); break; case "DATE": // vzrus: 31.03.10 dateTime and tz conversion int offTz; header.Date = NntpUtil.DecodeUTC(value, out offTz); header.TimeZoneOffset = offTz; break; case "FROM": header.From += NntpUtil.Base64HeaderDecode(value); break; case "NNTP-POSTING-HOST": header.PostingHost += value; break; case "LINES": header.LineCount = int.Parse(value); break; case "MIME-VERSION": part = new MIMEPart(); part.ContentType = "TEXT/PLAIN"; part.Charset = "US-ASCII"; part.ContentTransferEncoding = "7BIT"; part.Filename = null; part.Boundary = null; break; case "CONTENT-TYPE": if (part != null) { m = Regex.Match(response, @"CONTENT-TYPE: ""?([^""\s;]+)", RegexOptions.IgnoreCase); if (m.Success) { part.ContentType = m.Groups[1].ToString(); } m = Regex.Match(response, @"BOUNDARY=""?([^""\s;]+)", RegexOptions.IgnoreCase); if (m.Success) { part.Boundary = m.Groups[1].ToString(); part.EmbeddedPartList = new ArrayList(); } m = Regex.Match(response, @"CHARSET=""?([^""\s;]+)", RegexOptions.IgnoreCase); if (m.Success) { part.Charset = m.Groups[1].ToString(); } m = Regex.Match(response, @"NAME=""?([^""\s;]+)", RegexOptions.IgnoreCase); if (m.Success) { part.Filename = m.Groups[1].ToString(); } } break; case "CONTENT-TRANSFER-ENCODING": if (part != null) { m = Regex.Match(response, @"CONTENT-TRANSFER-ENCODING: ""?([^""\s;]+)", RegexOptions.IgnoreCase); if (m.Success) { part.ContentTransferEncoding = m.Groups[1].ToString(); } } break; } } return header; }
/// <summary> /// The dispatch mime content. /// </summary> /// <param name="sr"> /// The sr. /// </param> /// <param name="part"> /// The part. /// </param> /// <param name="seperator"> /// The seperator. /// </param> /// <returns> /// </returns> public static MIMEPart DispatchMIMEContent(StreamReader sr, MIMEPart part, string seperator) { string line = null; Match m = null; MemoryStream ms; byte[] bytes; switch (part.ContentType.Substring(0, part.ContentType.IndexOf('/')).ToUpper()) { case "MULTIPART": MIMEPart newPart = null; while ((line = sr.ReadLine()) != null && line != seperator && line != seperator + "--") { m = Regex.Match(line, @"CONTENT-TYPE: ""?([^""\s;]+)", RegexOptions.IgnoreCase); if (!m.Success) { continue; } newPart = new MIMEPart(); newPart.ContentType = m.Groups[1].ToString(); newPart.Charset = "US-ASCII"; newPart.ContentTransferEncoding = "7BIT"; while (line != string.Empty) { m = Regex.Match(line, @"BOUNDARY=""?([^""\s;]+)", RegexOptions.IgnoreCase); if (m.Success) { newPart.Boundary = m.Groups[1].ToString(); newPart.EmbeddedPartList = new ArrayList(); } m = Regex.Match(line, @"CHARSET=""?([^""\s;]+)", RegexOptions.IgnoreCase); if (m.Success) { newPart.Charset = m.Groups[1].ToString(); } m = Regex.Match(line, @"CONTENT-TRANSFER-ENCODING: ""?([^""\s;]+)", RegexOptions.IgnoreCase); if (m.Success) { newPart.ContentTransferEncoding = m.Groups[1].ToString(); } m = Regex.Match(line, @"NAME=""?([^""\s;]+)", RegexOptions.IgnoreCase); if (m.Success) { newPart.Filename = Base64HeaderDecode(m.Groups[1].ToString()); newPart.Filename = newPart.Filename.Substring(newPart.Filename.LastIndexOfAny(new[] { '\\', '/' }) + 1); } line = sr.ReadLine(); } part.EmbeddedPartList.Add(DispatchMIMEContent(sr, newPart, "--" + part.Boundary)); } break; case "TEXT": ms = new MemoryStream(); bytes = null; long pos; var msr = new StreamReader(ms, Encoding.GetEncoding(part.Charset)); var sb = new StringBuilder(); while ((line = sr.ReadLine()) != null && line != seperator && line != seperator + "--") { pos = ms.Position; if (line != string.Empty) { switch (part.ContentTransferEncoding.ToUpper()) { case "QUOTED-PRINTABLE": QuotedPrintableDecode(line, ms); break; case "BASE64": if (line != null && line != string.Empty) { Base64Decode(line, ms); } break; case "UU": if (line != null && line != string.Empty) { UUDecode(line, ms); } break; case "7BIT": bytes = Encoding.ASCII.GetBytes(line); ms.Write(bytes, 0, bytes.Length); ms.WriteByte((byte)'\n'); break; default: bytes = Encoding.ASCII.GetBytes(line); ms.Write(bytes, 0, bytes.Length); ms.WriteByte((byte)'\n'); break; } } ms.Position = pos; if (part.ContentType.ToUpper() == "TEXT/HTML") { sb.Append(msr.ReadToEnd()); } else { sb.Append(HttpUtility.HtmlEncode(msr.ReadToEnd()).Replace("\n", "<br>\n")); } } part.Text = sb.ToString(); break; default: ms = new MemoryStream(); bytes = null; while ((line = sr.ReadLine()) != null && line != seperator && line != seperator + "--") { if (line != string.Empty) { switch (part.ContentTransferEncoding.ToUpper()) { case "QUOTED-PRINTABLE": QuotedPrintableDecode(line, ms); break; case "BASE64": if (line != null && line != string.Empty) { Base64Decode(line, ms); } break; case "UU": if (line != null && line != string.Empty) { UUDecode(line, ms); } break; default: bytes = Encoding.ASCII.GetBytes(line); ms.Write(bytes, 0, bytes.Length); break; } } } ms.Seek(0, SeekOrigin.Begin); part.BinaryData = new byte[ms.Length]; ms.Read(part.BinaryData, 0, (int)ms.Length); break; } return(part); }
/// <summary> /// The dispatch mime content. /// </summary> /// <param name="sr"> /// The sr. /// </param> /// <param name="part"> /// The part. /// </param> /// <param name="seperator"> /// The seperator. /// </param> /// <returns> /// </returns> public static MIMEPart DispatchMIMEContent(StreamReader sr, MIMEPart part, string seperator) { string line = null; Match m = null; MemoryStream ms; byte[] bytes; switch (part.ContentType.Substring(0, part.ContentType.IndexOf('/')).ToUpper()) { case "MULTIPART": MIMEPart newPart = null; while ((line = sr.ReadLine()) != null && line != seperator && line != seperator + "--") { m = Regex.Match(line, @"CONTENT-TYPE: ""?([^""\s;]+)", RegexOptions.IgnoreCase); if (!m.Success) { continue; } newPart = new MIMEPart(); newPart.ContentType = m.Groups[1].ToString(); newPart.Charset = "US-ASCII"; newPart.ContentTransferEncoding = "7BIT"; while (line != string.Empty) { m = Regex.Match(line, @"BOUNDARY=""?([^""\s;]+)", RegexOptions.IgnoreCase); if (m.Success) { newPart.Boundary = m.Groups[1].ToString(); newPart.EmbeddedPartList = new ArrayList(); } m = Regex.Match(line, @"CHARSET=""?([^""\s;]+)", RegexOptions.IgnoreCase); if (m.Success) { newPart.Charset = m.Groups[1].ToString(); } m = Regex.Match(line, @"CONTENT-TRANSFER-ENCODING: ""?([^""\s;]+)", RegexOptions.IgnoreCase); if (m.Success) { newPart.ContentTransferEncoding = m.Groups[1].ToString(); } m = Regex.Match(line, @"NAME=""?([^""\s;]+)", RegexOptions.IgnoreCase); if (m.Success) { newPart.Filename = Base64HeaderDecode(m.Groups[1].ToString()); newPart.Filename = newPart.Filename.Substring(newPart.Filename.LastIndexOfAny(new[] { '\\', '/' }) + 1); } line = sr.ReadLine(); } part.EmbeddedPartList.Add(DispatchMIMEContent(sr, newPart, "--" + part.Boundary)); } break; case "TEXT": ms = new MemoryStream(); bytes = null; long pos; var msr = new StreamReader(ms, Encoding.GetEncoding(part.Charset)); var sb = new StringBuilder(); while ((line = sr.ReadLine()) != null && line != seperator && line != seperator + "--") { pos = ms.Position; if (line != string.Empty) { switch (part.ContentTransferEncoding.ToUpper()) { case "QUOTED-PRINTABLE": QuotedPrintableDecode(line, ms); break; case "BASE64": if (line != null && line != string.Empty) { Base64Decode(line, ms); } break; case "UU": if (line != null && line != string.Empty) { UUDecode(line, ms); } break; case "7BIT": bytes = Encoding.ASCII.GetBytes(line); ms.Write(bytes, 0, bytes.Length); ms.WriteByte((byte)'\n'); break; default: bytes = Encoding.ASCII.GetBytes(line); ms.Write(bytes, 0, bytes.Length); ms.WriteByte((byte)'\n'); break; } } ms.Position = pos; if (part.ContentType.ToUpper() == "TEXT/HTML") { sb.Append(msr.ReadToEnd()); } else { sb.Append(HttpUtility.HtmlEncode(msr.ReadToEnd()).Replace("\n", "<br>\n")); } } part.Text = sb.ToString(); break; default: ms = new MemoryStream(); bytes = null; while ((line = sr.ReadLine()) != null && line != seperator && line != seperator + "--") { if (line != string.Empty) { switch (part.ContentTransferEncoding.ToUpper()) { case "QUOTED-PRINTABLE": QuotedPrintableDecode(line, ms); break; case "BASE64": if (line != null && line != string.Empty) { Base64Decode(line, ms); } break; case "UU": if (line != null && line != string.Empty) { UUDecode(line, ms); } break; default: bytes = Encoding.ASCII.GetBytes(line); ms.Write(bytes, 0, bytes.Length); break; } } } ms.Seek(0, SeekOrigin.Begin); part.BinaryData = new byte[ms.Length]; ms.Read(part.BinaryData, 0, (int)ms.Length); break; } return part; }
/// <summary> /// The get header. /// </summary> /// <param name="messageId"> /// The message id. /// </param> /// <param name="part"> /// The part. /// </param> /// <returns> /// </returns> private ArticleHeader GetHeader(string messageId, out MIMEPart part) { string response = null; var header = new ArticleHeader(); string name = null; string value = null; header.ReferenceIds = new string[0]; string[] values = null; string[] values2 = null; Match m = null; part = null; int i = -1; while ((response = this.sr.ReadLine()) != null && response != string.Empty) { m = Regex.Match(response, @"^\s+(\S+)$"); if (m.Success) { value = m.Groups[1].ToString(); } else { i = response.IndexOf(':'); if (i == -1) { continue; } name = response.Substring(0, i).ToUpper(); value = response.Substring(i + 1); } switch (name) { case "REFERENCES": values = value.Trim().Split(' '); values2 = header.ReferenceIds; header.ReferenceIds = new string[values.Length + values2.Length]; values.CopyTo(header.ReferenceIds, 0); values2.CopyTo(header.ReferenceIds, values.Length); break; case "SUBJECT": header.Subject += NntpUtil.Base64HeaderDecode(value); break; case "DATE": // vzrus: 31.03.10 dateTime and tz conversion int offTz; header.Date = NntpUtil.DecodeUTC(value, out offTz); header.TimeZoneOffset = offTz; break; case "FROM": header.From += NntpUtil.Base64HeaderDecode(value); break; case "NNTP-POSTING-HOST": header.PostingHost += value; break; case "LINES": header.LineCount = int.Parse(value); break; case "MIME-VERSION": part = new MIMEPart(); part.ContentType = "TEXT/PLAIN"; part.Charset = "US-ASCII"; part.ContentTransferEncoding = "7BIT"; part.Filename = null; part.Boundary = null; break; case "CONTENT-TYPE": if (part != null) { m = Regex.Match(response, @"CONTENT-TYPE: ""?([^""\s;]+)", RegexOptions.IgnoreCase); if (m.Success) { part.ContentType = m.Groups[1].ToString(); } m = Regex.Match(response, @"BOUNDARY=""?([^""\s;]+)", RegexOptions.IgnoreCase); if (m.Success) { part.Boundary = m.Groups[1].ToString(); part.EmbeddedPartList = new ArrayList(); } m = Regex.Match(response, @"CHARSET=""?([^""\s;]+)", RegexOptions.IgnoreCase); if (m.Success) { part.Charset = m.Groups[1].ToString(); } m = Regex.Match(response, @"NAME=""?([^""\s;]+)", RegexOptions.IgnoreCase); if (m.Success) { part.Filename = m.Groups[1].ToString(); } } break; case "CONTENT-TRANSFER-ENCODING": if (part != null) { m = Regex.Match(response, @"CONTENT-TRANSFER-ENCODING: ""?([^""\s;]+)", RegexOptions.IgnoreCase); if (m.Success) { part.ContentTransferEncoding = m.Groups[1].ToString(); } } break; } } return(header); }