static void ExtractAttachments(TnefReader reader, BodyBuilder builder) { var attachMethod = TnefAttachMethod.ByValue; var filter = new BestEncodingFilter(); var prop = reader.TnefPropertyReader; MimePart attachment = null; int outIndex, outLength; TnefAttachFlags flags; string[] mimeType; byte[] attachData; string text; do { if (reader.AttributeLevel != TnefAttributeLevel.Attachment) { break; } switch (reader.AttributeTag) { case TnefAttributeTag.AttachRenderData: attachMethod = TnefAttachMethod.ByValue; attachment = new MimePart(); break; case TnefAttributeTag.Attachment: if (attachment == null) { break; } attachData = null; while (prop.ReadNextProperty()) { switch (prop.PropertyTag.Id) { case TnefPropertyId.AttachLongFilename: attachment.FileName = prop.ReadValueAsString(); break; case TnefPropertyId.AttachFilename: if (attachment.FileName == null) { attachment.FileName = prop.ReadValueAsString(); } break; case TnefPropertyId.AttachContentLocation: attachment.ContentLocation = prop.ReadValueAsUri(); break; case TnefPropertyId.AttachContentBase: attachment.ContentBase = prop.ReadValueAsUri(); break; case TnefPropertyId.AttachContentId: text = prop.ReadValueAsString(); var buffer = CharsetUtils.UTF8.GetBytes(text); int index = 0; if (ParseUtils.TryParseMsgId(buffer, ref index, buffer.Length, false, false, out string msgid)) { attachment.ContentId = msgid; } break; case TnefPropertyId.AttachDisposition: text = prop.ReadValueAsString(); if (ContentDisposition.TryParse(text, out ContentDisposition disposition)) { attachment.ContentDisposition = disposition; } break; case TnefPropertyId.AttachData: attachData = prop.ReadValueAsBytes(); break; case TnefPropertyId.AttachMethod: attachMethod = (TnefAttachMethod)prop.ReadValueAsInt32(); break; case TnefPropertyId.AttachMimeTag: mimeType = prop.ReadValueAsString().Split('/'); if (mimeType.Length == 2) { attachment.ContentType.MediaType = mimeType[0].Trim(); attachment.ContentType.MediaSubtype = mimeType[1].Trim(); } break; case TnefPropertyId.AttachFlags: flags = (TnefAttachFlags)prop.ReadValueAsInt32(); if ((flags & TnefAttachFlags.RenderedInBody) != 0) { if (attachment.ContentDisposition == null) { attachment.ContentDisposition = new ContentDisposition(ContentDisposition.Inline); } else { attachment.ContentDisposition.Disposition = ContentDisposition.Inline; } } break; case TnefPropertyId.AttachSize: if (attachment.ContentDisposition == null) { attachment.ContentDisposition = new ContentDisposition(); } attachment.ContentDisposition.Size = prop.ReadValueAsInt64(); break; case TnefPropertyId.DisplayName: attachment.ContentType.Name = prop.ReadValueAsString(); break; } } if (attachData != null) { int count = attachData.Length; int index = 0; if (attachMethod == TnefAttachMethod.EmbeddedMessage) { attachment.ContentTransferEncoding = ContentEncoding.Base64; attachment = PromoteToTnefPart(attachment); count -= 16; index = 16; } else { filter.Flush(attachData, index, count, out outIndex, out outLength); attachment.ContentTransferEncoding = filter.GetBestEncoding(EncodingConstraint.SevenBit); filter.Reset(); } attachment.Content = new MimeContent(new MemoryStream(attachData, index, count, false)); builder.Attachments.Add(attachment); } break; case TnefAttributeTag.AttachCreateDate: if (attachment != null) { if (attachment.ContentDisposition == null) { attachment.ContentDisposition = new ContentDisposition(); } attachment.ContentDisposition.CreationDate = prop.ReadValueAsDateTime(); } break; case TnefAttributeTag.AttachModifyDate: if (attachment != null) { if (attachment.ContentDisposition == null) { attachment.ContentDisposition = new ContentDisposition(); } attachment.ContentDisposition.ModificationDate = prop.ReadValueAsDateTime(); } break; case TnefAttributeTag.AttachTitle: if (attachment != null && string.IsNullOrEmpty(attachment.FileName)) { attachment.FileName = prop.ReadValueAsString(); } break; case TnefAttributeTag.AttachMetaFile: if (attachment == null) { break; } // TODO: what to do with the meta data? break; case TnefAttributeTag.AttachData: if (attachment == null || attachMethod != TnefAttachMethod.ByValue) { break; } attachData = prop.ReadValueAsBytes(); filter.Flush(attachData, 0, attachData.Length, out outIndex, out outLength); attachment.ContentTransferEncoding = filter.GetBestEncoding(EncodingConstraint.SevenBit); attachment.Content = new MimeContent(new MemoryStream(attachData, false)); filter.Reset(); builder.Attachments.Add(attachment); break; } } while (reader.ReadNextAttribute()); }
public static string GetFileName(this MimeEntity mimeEntity) { var contentDispositionHeader = mimeEntity.Headers.FirstOrDefault(x => x.Field.Equals("Content-Disposition", StringComparison.InvariantCultureIgnoreCase)); if (contentDispositionHeader != null && ContentDisposition.TryParse(contentDispositionHeader.Value, out var contentDisposition)) { if (!string.IsNullOrEmpty(contentDisposition.FileName)) { return(contentDisposition.FileName); } } var contentTypeHeader = mimeEntity.Headers.FirstOrDefault(x => x.Field.Equals("Content-Type", StringComparison.InvariantCultureIgnoreCase)); if (contentTypeHeader == null) { return(null); } if (!ContentType.TryParse(contentTypeHeader.Value, out var contentType)) { return(null); } return(!string.IsNullOrEmpty(contentType.Name) ? contentType.Name : null); }
static ContentDisposition ParseContentDisposition(ImapEngine engine, CancellationToken cancellationToken) { var token = engine.ReadToken (cancellationToken); if (token.Type == ImapTokenType.Nil) return null; if (token.Type != ImapTokenType.OpenParen) throw ImapEngine.UnexpectedToken (token, false); var dsp = ReadStringToken (engine, cancellationToken); var builder = new StringBuilder (dsp); ContentDisposition disposition; token = engine.ReadToken (cancellationToken); if (token.Type == ImapTokenType.OpenParen) ParseParameterList (builder, engine, cancellationToken); else if (token.Type != ImapTokenType.Nil) throw ImapEngine.UnexpectedToken (token, false); token = engine.ReadToken (cancellationToken); if (token.Type != ImapTokenType.CloseParen) throw ImapEngine.UnexpectedToken (token, false); if (!ContentDisposition.TryParse (builder.ToString (), out disposition)) disposition = new ContentDisposition (dsp); return disposition; }
public void TestUnquotedFilenameParameterValues() { const string text = " attachment; filename=Partnership Marketing Agreement\n Form - Mega Brands - Easter Toys - Week 11.pdf"; ContentDisposition disposition; Assert.IsTrue(ContentDisposition.TryParse(text, out disposition), "Failed to parse Content-Disposition"); Assert.AreEqual("Partnership Marketing Agreement Form - Mega Brands - Easter Toys - Week 11.pdf", disposition.FileName, "The filename value does not match."); }
public void TestIssue239() { const string text = " attachment; size=1049971;\n\tfilename*=\"utf-8''SBD%20%C5%A0kodov%C3%A1k%2Ejpg\""; const string expected = "SBD Škodovák.jpg"; ContentDisposition disposition; Assert.IsTrue(ContentDisposition.TryParse(text, out disposition), "Failed to parse Content-Disposition"); Assert.AreEqual(expected, disposition.FileName, "The filename value does not match."); }
public void TestFormData() { const string text = "form-data; filename=\"form.txt\""; ContentDisposition disposition; Assert.IsTrue(ContentDisposition.TryParse(text, out disposition), "Failed to parse Content-Disposition"); Assert.AreEqual("form-data", disposition.Disposition, "The disposition values do not match."); Assert.AreEqual("form.txt", disposition.FileName, "The filename value does not match."); }
public void TestMistakenlyQuotedEncodedParameterValues() { const string text = "attachment;\n filename*0*=\"ISO-8859-2''%C8%50%50%20%2D%20%BE%E1%64%6F%73%74%20%6F%20%61%6B%63%65\";\n " + "filename*1*=\"%70%74%61%63%69%20%73%6D%6C%6F%75%76%79%20%31%32%2E%31%32%2E\";\n " + "filename*2*=\"%64%6F%63\""; ContentDisposition disposition; Assert.IsTrue(ContentDisposition.TryParse(text, out disposition), "Failed to parse Content-Disposition"); Assert.AreEqual("ČPP - žádost o akceptaci smlouvy 12.12.doc", disposition.FileName, "The filename value does not match."); }
public void TestMultipleParametersWithIdenticalNames() { ContentDisposition disposition; const string text1 = "inline;\n filename=\"Filename.doc\";\n filename*0*=UTF-8''UnicodeFile;\n filename*1*=name.doc"; Assert.IsTrue(ContentDisposition.TryParse(text1, out disposition), "Failed to parse first Content-Disposition"); Assert.AreEqual("UnicodeFilename.doc", disposition.FileName, "The first filename value does not match."); const string text2 = "inline;\n filename*0*=UTF-8''UnicodeFile;\n filename*1*=name.doc;\n filename=\"Filename.doc\""; Assert.IsTrue(ContentDisposition.TryParse(text2, out disposition), "Failed to parse second Content-Disposition"); Assert.AreEqual("UnicodeFilename.doc", disposition.FileName, "The second filename value does not match."); const string text3 = "inline;\n filename*0*=UTF-8''UnicodeFile;\n filename=\"Filename.doc\";\n filename*1*=name.doc"; Assert.IsTrue(ContentDisposition.TryParse(text3, out disposition), "Failed to parse third Content-Disposition"); Assert.AreEqual("UnicodeFilename.doc", disposition.FileName, "The third filename value does not match."); }
public void TestUnquotedFilenameParameterValues() { const string text = " attachment; filename=Partnership Marketing Agreement\n Form - Mega Brands - Easter Toys - Week 11.pdf"; const string expected = "Partnership Marketing Agreement Form - Mega Brands - Easter Toys - Week 11.pdf"; var buffer = Encoding.ASCII.GetBytes(text); ContentDisposition disposition; Assert.IsTrue(ContentDisposition.TryParse(text, out disposition), "Failed to parse Content-Disposition"); Assert.AreEqual(expected, disposition.FileName, "The filename value does not match."); Assert.IsTrue(ContentDisposition.TryParse(buffer, 0, buffer.Length, out disposition), "Failed to parse Content-Disposition"); Assert.AreEqual(expected, disposition.FileName, "The filename value does not match."); Assert.IsTrue(ContentDisposition.TryParse(buffer, 0, out disposition), "Failed to parse Content-Disposition"); Assert.AreEqual(expected, disposition.FileName, "The filename value does not match."); Assert.IsTrue(ContentDisposition.TryParse(buffer, out disposition), "Failed to parse Content-Disposition"); Assert.AreEqual(expected, disposition.FileName, "The filename value does not match."); }
public void TestChineseFilename() { const string expected = " attachment;\n\tfilename*=gb18030''%B2%E2%CA%D4%CE%C4%B1%BE.txt\n"; var disposition = new ContentDisposition(ContentDisposition.Attachment); disposition.Parameters.Add("GB18030", "filename", "测试文本.txt"); var format = FormatOptions.Default.Clone(); format.NewLineFormat = NewLineFormat.Unix; var encoded = disposition.Encode(format, Encoding.UTF8); Parameter param; Assert.AreEqual(expected, encoded, "The encoded Chinese filename parameter does not match the expected value."); Assert.IsTrue(ContentDisposition.TryParse(encoded, out disposition), "Failed to parse Content-Disposition"); Assert.AreEqual("测试文本.txt", disposition.FileName, "The decoded Chinese filename does not match."); Assert.IsTrue(disposition.Parameters.TryGetValue("filename", out param), "Failed to locate filename parameter."); Assert.AreEqual("GB18030", param.Encoding.HeaderName, "The filename encoding did not match."); }
public void TestChineseFilename2047() { const string expected = " attachment; filename=\"=?gb18030?b?suLK1M7Esb4udHh0?=\"\n"; var disposition = new ContentDisposition(ContentDisposition.Attachment); disposition.Parameters.Add("GB18030", "filename", "测试文本.txt"); var format = FormatOptions.Default.Clone(); format.ParameterEncodingMethod = ParameterEncodingMethod.Rfc2047; format.NewLineFormat = NewLineFormat.Unix; var encoded = disposition.Encode(format, Encoding.UTF8); Parameter param; Assert.AreEqual(expected, encoded, "The encoded Chinese filename parameter does not match the expected value."); Assert.IsTrue(ContentDisposition.TryParse(encoded, out disposition), "Failed to parse Content-Disposition"); Assert.AreEqual("测试文本.txt", disposition.FileName, "The decoded Chinese filename does not match."); Assert.IsTrue(disposition.Parameters.TryGetValue("filename", out param), "Failed to locate filename parameter."); Assert.AreEqual("GB18030", param.Encoding.HeaderName, "The filename encoding did not match."); }
public void TestFormData() { const string text = "form-data; filename=\"form.txt\""; var buffer = Encoding.ASCII.GetBytes(text); ContentDisposition disposition; Assert.IsTrue(ContentDisposition.TryParse(text, out disposition), "Failed to parse Content-Disposition"); Assert.AreEqual("form-data", disposition.Disposition, "The disposition values do not match."); Assert.AreEqual("form.txt", disposition.FileName, "The filename value does not match."); Assert.IsTrue(ContentDisposition.TryParse(buffer, 0, buffer.Length, out disposition), "Failed to parse Content-Disposition"); Assert.AreEqual("form-data", disposition.Disposition, "The disposition values do not match."); Assert.AreEqual("form.txt", disposition.FileName, "The filename value does not match."); Assert.IsTrue(ContentDisposition.TryParse(buffer, 0, out disposition), "Failed to parse Content-Disposition"); Assert.AreEqual("form-data", disposition.Disposition, "The disposition values do not match."); Assert.AreEqual("form.txt", disposition.FileName, "The filename value does not match."); Assert.IsTrue(ContentDisposition.TryParse(buffer, out disposition), "Failed to parse Content-Disposition"); Assert.AreEqual("form-data", disposition.Disposition, "The disposition values do not match."); Assert.AreEqual("form.txt", disposition.FileName, "The filename value does not match."); }
static void AssertParse(string text, ContentDisposition expected, bool result = true, int tokenIndex = -1, int errorIndex = -1) { var buffer = Encoding.UTF8.GetBytes(text); var options = ParserOptions.Default; ContentDisposition disposition; Assert.AreEqual(result, ContentDisposition.TryParse(text, out disposition), "Unexpected result for TryParse: {0}", text); AssertParseResults(disposition, expected); Assert.AreEqual(result, ContentDisposition.TryParse(options, text, out disposition), "Unexpected result for TryParse: {0}", text); AssertParseResults(disposition, expected); Assert.AreEqual(result, ContentDisposition.TryParse(buffer, out disposition), "Unexpected result for TryParse: {0}", text); AssertParseResults(disposition, expected); Assert.AreEqual(result, ContentDisposition.TryParse(options, buffer, out disposition), "Unexpected result for TryParse: {0}", text); AssertParseResults(disposition, expected); Assert.AreEqual(result, ContentDisposition.TryParse(buffer, 0, out disposition), "Unexpected result for TryParse: {0}", text); AssertParseResults(disposition, expected); Assert.AreEqual(result, ContentDisposition.TryParse(options, buffer, 0, out disposition), "Unexpected result for TryParse: {0}", text); AssertParseResults(disposition, expected); Assert.AreEqual(result, ContentDisposition.TryParse(buffer, 0, buffer.Length, out disposition), "Unexpected result for TryParse: {0}", text); AssertParseResults(disposition, expected); Assert.AreEqual(result, ContentDisposition.TryParse(options, buffer, 0, buffer.Length, out disposition), "Unexpected result for TryParse: {0}", text); AssertParseResults(disposition, expected); try { disposition = ContentDisposition.Parse(text); if (tokenIndex != -1 && errorIndex != -1) { Assert.Fail("Parsing \"{0}\" should have failed.", text); } AssertParseResults(disposition, expected); } catch (ParseException ex) { Assert.AreEqual(tokenIndex, ex.TokenIndex, "Unexpected token index"); Assert.AreEqual(errorIndex, ex.ErrorIndex, "Unexpected error index"); } catch (Exception e) { Assert.Fail("Unexpected exception: {0}", e); } try { disposition = ContentDisposition.Parse(options, text); if (tokenIndex != -1 && errorIndex != -1) { Assert.Fail("Parsing \"{0}\" should have failed.", text); } AssertParseResults(disposition, expected); } catch (ParseException ex) { Assert.AreEqual(tokenIndex, ex.TokenIndex, "Unexpected token index"); Assert.AreEqual(errorIndex, ex.ErrorIndex, "Unexpected error index"); } catch (Exception e) { Assert.Fail("Unexpected exception: {0}", e); } try { disposition = ContentDisposition.Parse(buffer); if (tokenIndex != -1 && errorIndex != -1) { Assert.Fail("Parsing \"{0}\" should have failed.", text); } AssertParseResults(disposition, expected); } catch (ParseException ex) { Assert.AreEqual(tokenIndex, ex.TokenIndex, "Unexpected token index"); Assert.AreEqual(errorIndex, ex.ErrorIndex, "Unexpected error index"); } catch (Exception e) { Assert.Fail("Unexpected exception: {0}", e); } try { disposition = ContentDisposition.Parse(options, buffer); if (tokenIndex != -1 && errorIndex != -1) { Assert.Fail("Parsing \"{0}\" should have failed.", text); } AssertParseResults(disposition, expected); } catch (ParseException ex) { Assert.AreEqual(tokenIndex, ex.TokenIndex, "Unexpected token index"); Assert.AreEqual(errorIndex, ex.ErrorIndex, "Unexpected error index"); } catch (Exception e) { Assert.Fail("Unexpected exception: {0}", e); } try { disposition = ContentDisposition.Parse(buffer, 0); if (tokenIndex != -1 && errorIndex != -1) { Assert.Fail("Parsing \"{0}\" should have failed.", text); } AssertParseResults(disposition, expected); } catch (ParseException ex) { Assert.AreEqual(tokenIndex, ex.TokenIndex, "Unexpected token index"); Assert.AreEqual(errorIndex, ex.ErrorIndex, "Unexpected error index"); } catch (Exception e) { Assert.Fail("Unexpected exception: {0}", e); } try { disposition = ContentDisposition.Parse(options, buffer, 0); if (tokenIndex != -1 && errorIndex != -1) { Assert.Fail("Parsing \"{0}\" should have failed.", text); } AssertParseResults(disposition, expected); } catch (ParseException ex) { Assert.AreEqual(tokenIndex, ex.TokenIndex, "Unexpected token index"); Assert.AreEqual(errorIndex, ex.ErrorIndex, "Unexpected error index"); } catch (Exception e) { Assert.Fail("Unexpected exception: {0}", e); } try { disposition = ContentDisposition.Parse(buffer, 0, buffer.Length); if (tokenIndex != -1 && errorIndex != -1) { Assert.Fail("Parsing \"{0}\" should have failed.", text); } AssertParseResults(disposition, expected); } catch (ParseException ex) { Assert.AreEqual(tokenIndex, ex.TokenIndex, "Unexpected token index"); Assert.AreEqual(errorIndex, ex.ErrorIndex, "Unexpected error index"); } catch (Exception e) { Assert.Fail("Unexpected exception: {0}", e); } try { disposition = ContentDisposition.Parse(options, buffer, 0, buffer.Length); if (tokenIndex != -1 && errorIndex != -1) { Assert.Fail("Parsing \"{0}\" should have failed.", text); } AssertParseResults(disposition, expected); } catch (ParseException ex) { Assert.AreEqual(tokenIndex, ex.TokenIndex, "Unexpected token index"); Assert.AreEqual(errorIndex, ex.ErrorIndex, "Unexpected error index"); } catch (Exception e) { Assert.Fail("Unexpected exception: {0}", e); } }