Esempio n. 1
1
        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());
        }
Esempio n. 2
0
        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);
        }
Esempio n. 3
0
        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;
        }
Esempio n. 4
0
        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.");
        }
Esempio n. 5
0
        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.");
        }
Esempio n. 6
0
        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.");
        }
Esempio n. 7
0
        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.");
        }
Esempio n. 8
0
        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.");
        }
Esempio n. 9
0
        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.");
        }
Esempio n. 10
0
        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.");
        }
Esempio n. 11
0
        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.");
        }
Esempio n. 12
0
        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.");
        }
Esempio n. 13
0
        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);
            }
        }