public async Task TestWriteAsync() { using (var original = new MemoryStream()) { using (var file = File.OpenRead(Path.Combine(DataDir, "photo.jpg"))) file.CopyTo(original, 4096); using (var decoded = new MemoryStream()) { using (var file = File.OpenRead(Path.Combine(DataDir, "photo.b64"))) { using (var filtered = new FilteredStream(decoded)) { filtered.Add(DecoderFilter.Create(ContentEncoding.Base64)); await file.CopyToAsync(filtered, 4096); await filtered.FlushAsync(); } } var buf0 = original.GetBuffer(); var buf1 = decoded.GetBuffer(); int n = (int)original.Length; Assert.AreEqual(original.Length, decoded.Length, "Decoded length is incorrect."); for (int i = 0; i < n; i++) { Assert.AreEqual(buf0[i], buf1[i], "The byte at offset {0} does not match.", i); } } } }
/// <summary> /// Computes the md5sum of the content. /// </summary> /// <returns>The md5sum of the content.</returns> /// <exception cref="System.InvalidOperationException"> /// The <see cref="ContentObject"/> is <c>null</c>. /// </exception> public string ComputeContentMd5() { if (ContentObject == null) { throw new InvalidOperationException("Cannot compute Md5 checksum without a ContentObject."); } var stream = ContentObject.Stream; stream.Seek(0, SeekOrigin.Begin); byte[] checksum; using (var filtered = new FilteredStream(stream)) { if (ContentObject.Encoding > ContentEncoding.Binary) { filtered.Add(DecoderFilter.Create(ContentObject.Encoding)); } if (ContentType.Matches("text", "*")) { filtered.Add(new Unix2DosFilter()); } using (var md5 = MD5.Create()) checksum = md5.ComputeHash(filtered); } var base64 = new Base64Encoder(true); var digest = new byte[base64.EstimateOutputLength(checksum.Length)]; int n = base64.Flush(checksum, 0, checksum.Length, digest); return(Encoding.ASCII.GetString(digest, 0, n)); }
public void TestBase64Decode() { using (var original = new MemoryStream()) { using (var file = File.OpenRead("../../TestData/encoders/photo.jpg")) file.CopyTo(original, 4096); using (var decoded = new MemoryStream()) { using (var file = File.OpenRead("../../TestData/encoders/photo.b64")) { using (var filtered = new FilteredStream(file)) { filtered.Add(DecoderFilter.Create(ContentEncoding.Base64)); filtered.CopyTo(decoded, 4096); } } var buf0 = original.GetBuffer(); var buf1 = decoded.GetBuffer(); int n = (int)original.Length; Assert.AreEqual(original.Length, decoded.Length, "Decoded length is incorrect."); for (int i = 0; i < n; i++) { Assert.AreEqual(buf0[i], buf1[i], "The byte at offset {0} does not match.", i); } } } }
public void TestCreateEncoders() { Assert.Throws <ArgumentNullException> (() => EncoderFilter.Create(null)); Assert.Throws <ArgumentNullException> (() => DecoderFilter.Create(null)); AssertIsEncoderFilter(ContentEncoding.Base64, ContentEncoding.Base64); AssertIsEncoderFilter("base64", ContentEncoding.Base64); Assert.IsInstanceOf <PassThroughFilter> (EncoderFilter.Create(ContentEncoding.Binary)); Assert.IsInstanceOf <PassThroughFilter> (EncoderFilter.Create("binary")); Assert.IsInstanceOf <PassThroughFilter> (EncoderFilter.Create(ContentEncoding.Default)); Assert.IsInstanceOf <PassThroughFilter> (EncoderFilter.Create("x-invalid")); Assert.IsInstanceOf <PassThroughFilter> (EncoderFilter.Create(ContentEncoding.EightBit)); Assert.IsInstanceOf <PassThroughFilter> (EncoderFilter.Create("8bit")); AssertIsEncoderFilter(ContentEncoding.QuotedPrintable, ContentEncoding.QuotedPrintable); AssertIsEncoderFilter("quoted-printable", ContentEncoding.QuotedPrintable); Assert.IsInstanceOf <PassThroughFilter> (EncoderFilter.Create(ContentEncoding.SevenBit)); Assert.IsInstanceOf <PassThroughFilter> (EncoderFilter.Create("7bit")); AssertIsEncoderFilter(ContentEncoding.UUEncode, ContentEncoding.UUEncode); AssertIsEncoderFilter("x-uuencode", ContentEncoding.UUEncode); AssertIsEncoderFilter("uuencode", ContentEncoding.UUEncode); }
void TestDecoder(ContentEncoding encoding, byte[] rawData, string encodedFile, int bufferSize) { int n; using (var original = new MemoryStream(rawData, false)) { using (var decoded = new MemoryStream()) { using (var filtered = new FilteredStream(decoded)) { filtered.Add(DecoderFilter.Create(encoding)); using (var file = File.OpenRead(Path.Combine(dataDir, encodedFile))) { var buffer = new byte[bufferSize]; while ((n = file.Read(buffer, 0, bufferSize)) > 0) { filtered.Write(buffer, 0, n); } } filtered.Flush(); } var buf = decoded.GetBuffer(); n = rawData.Length; Assert.AreEqual(rawData.Length, decoded.Length, "Decoded length is incorrect."); for (int i = 0; i < n; i++) { Assert.AreEqual(rawData[i], buf[i], "The byte at offset {0} does not match.", i); } } } }
/// <summary> /// Join the specified message/partial parts into the complete message. /// </summary> /// <param name="options">The parser options to use.</param> /// <param name="partials">The list of partial message parts.</param> /// <exception cref="System.ArgumentNullException"> /// <para><paramref name="options"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="partials"/>is <c>null</c>.</para> /// </exception> public static MimeMessage Join(ParserOptions options, IEnumerable <MessagePartial> partials) { if (options == null) { throw new ArgumentNullException("options"); } if (partials == null) { throw new ArgumentNullException("partials"); } var parts = partials.ToList(); if (parts.Count == 0) { return(null); } parts.Sort(PartialCompare); if (!parts[parts.Count - 1].Total.HasValue) { throw new ArgumentException("partials"); } int total = parts[parts.Count - 1].Total.Value; if (parts.Count != total) { throw new ArgumentException("partials"); } string id = parts[0].Id; using (var chained = new ChainedStream()) { // chain all of the partial content streams... for (int i = 0; i < parts.Count; i++) { int number = parts[i].Number.Value; if (number != i + 1) { throw new ArgumentException("partials"); } var content = parts[i].ContentObject; content.Stream.Seek(0, SeekOrigin.Begin); var filtered = new FilteredStream(content.Stream); filtered.Add(DecoderFilter.Create(content.Encoding)); chained.Add(filtered); } var parser = new MimeParser(options, chained); return(parser.ParseMessage()); } }
/// <summary> /// Opens the decoded content stream. /// </summary> /// <remarks> /// Provides a means of reading the decoded content without having to first write it to another /// stream using <see cref="DecodeTo(System.IO.Stream,System.Threading.CancellationToken)"/>. /// </remarks> /// <returns>The decoded content stream.</returns> public Stream Open() { content.Seek(0, SeekOrigin.Begin); var filtered = new FilteredStream(content); filtered.Add(DecoderFilter.Create(Encoding)); return(filtered); }
static void AssertIsDecoderFilter(string encoding, ContentEncoding expected) { var filter = DecoderFilter.Create(encoding); Assert.IsInstanceOf <DecoderFilter> (filter, "Expected DecoderFilter for \"{0}\"", encoding); var decoder = (DecoderFilter)filter; Assert.AreEqual(expected, decoder.Encoding, "Expected decoder's Encoding to be ContentEncoding.{0}", expected); }
public void TestBase64Decode() { using (var original = new MemoryStream()) { using (var file = File.OpenRead("../../TestData/encoders/photo.jpg")) file.CopyTo(original, 4096); using (var decoded = new MemoryStream()) { using (var file = File.OpenRead("../../TestData/encoders/photo.b64")) { using (var filtered = new FilteredStream(file)) { filtered.Add(DecoderFilter.Create(ContentEncoding.Base64)); filtered.CopyTo(decoded, 4096); } } var buf0 = original.GetBuffer(); var buf1 = decoded.GetBuffer(); int n = (int)original.Length; Assert.AreEqual(original.Length, decoded.Length, "Decoded length is incorrect."); for (int i = 0; i < n; i++) { Assert.AreEqual(buf0[i], buf1[i], "The byte at offset {0} does not match.", i); } } } var decoder = new Base64Decoder(); var output = new byte[4096]; Assert.AreEqual(ContentEncoding.Base64, decoder.Encoding); for (int i = 0; i < base64EncodedPatterns.Length; i++) { decoder.Reset(); var buf = Encoding.ASCII.GetBytes(base64EncodedPatterns[i]); int n = decoder.Decode(buf, 0, buf.Length, output); var actual = Encoding.ASCII.GetString(output, 0, n); Assert.AreEqual(base64DecodedPatterns[i], actual, "Failed to decode base64EncodedPatterns[{0}]", i); } for (int i = 0; i < base64EncodedLongPatterns.Length; i++) { decoder.Reset(); var buf = Encoding.ASCII.GetBytes(base64EncodedLongPatterns[i]); int n = decoder.Decode(buf, 0, buf.Length, output); for (int j = 0; j < n; j++) { Assert.AreEqual(output[j], (byte)(j + i), "Failed to decode base64EncodedLongPatterns[{0}]", i); } } }
/// <summary> /// Decodes the content stream into another stream. /// </summary> /// <remarks> /// Uses the <see cref="Encoding"/> to decode the content stream to the output stream. /// </remarks> /// <param name="stream">The output stream.</param> /// <param name="cancellationToken">A cancellation token.</param> /// <exception cref="System.ArgumentNullException"> /// <paramref name="stream"/> is <c>null</c>. /// </exception> /// <exception cref="System.OperationCanceledException"> /// The operation was canceled via the cancellation token. /// </exception> /// <exception cref="System.IO.IOException"> /// An I/O error occurred. /// </exception> public void DecodeTo(Stream stream, CancellationToken cancellationToken = default(CancellationToken)) { if (stream == null) { throw new ArgumentNullException("stream"); } using (var filtered = new FilteredStream(stream)) { filtered.Add(DecoderFilter.Create(Encoding)); WriteTo(filtered, cancellationToken); filtered.Flush(cancellationToken); } }
/// <summary> /// Decodes the content stream into another stream. /// </summary> /// <param name="stream">The output stream.</param> /// <exception cref="System.ArgumentNullException"> /// <paramref name="stream"/> is <c>null</c>. /// </exception> public void DecodeTo(Stream stream) { if (stream == null) { throw new ArgumentNullException("stream"); } using (var filtered = new FilteredStream(stream)) { filtered.Add(DecoderFilter.Create(Encoding)); WriteTo(filtered); filtered.Flush(); } }
/// <summary> /// Asynchronously decodes the content stream into another stream. /// </summary> /// <remarks> /// If the content stream is encoded, this method will decode it into the output stream /// using a suitable decoder based on the <see cref="Encoding"/> property, otherwise the /// stream will be copied into the output stream as-is. /// </remarks> /// <param name="stream">The output stream.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <exception cref="System.ArgumentNullException"> /// <paramref name="stream"/> is <c>null</c>. /// </exception> /// <exception cref="System.OperationCanceledException"> /// The operation was canceled via the cancellation token. /// </exception> /// <exception cref="System.IO.IOException"> /// An I/O error occurred. /// </exception> /// <example> /// <code language="c#" source="Examples\AttachmentExamples.cs" region="SaveAttachments" /> /// </example> public async Task DecodeToAsync(Stream stream, CancellationToken cancellationToken = default(CancellationToken)) { if (stream == null) { throw new ArgumentNullException(nameof(stream)); } using (var filtered = new FilteredStream(stream)) { filtered.Add(DecoderFilter.Create(Encoding)); await WriteToAsync(filtered, cancellationToken).ConfigureAwait(false); await filtered.FlushAsync(cancellationToken).ConfigureAwait(false); } }
public void TestFilterArguments() { AssertFilterArguments(new Dos2UnixFilter()); AssertFilterArguments(new Unix2DosFilter()); AssertFilterArguments(new ArmoredFromFilter()); AssertFilterArguments(new BestEncodingFilter()); AssertFilterArguments(new CharsetFilter("iso-8859-1", "utf-8")); AssertFilterArguments(DecoderFilter.Create(ContentEncoding.Base64)); AssertFilterArguments(EncoderFilter.Create(ContentEncoding.Base64)); AssertFilterArguments(DecoderFilter.Create(ContentEncoding.QuotedPrintable)); AssertFilterArguments(EncoderFilter.Create(ContentEncoding.QuotedPrintable)); AssertFilterArguments(DecoderFilter.Create(ContentEncoding.UUEncode)); AssertFilterArguments(EncoderFilter.Create(ContentEncoding.UUEncode)); AssertFilterArguments(new TrailingWhitespaceFilter()); AssertFilterArguments(new DkimRelaxedBodyFilter()); AssertFilterArguments(new DkimSimpleBodyFilter()); }