/// <summary> /// Load a <see cref="MimeEntity"/> from the specified content stream. /// </summary> /// <remarks> /// This method is mostly meant for use with APIs such as <see cref="System.Net.HttpWebResponse"/> /// where the headers are parsed separately from the content. /// </remarks> /// <returns>The parsed MIME entity.</returns> /// <param name="options">The parser options.</param> /// <param name="contentType">The Content-Type of the stream.</param> /// <param name="content">The content stream.</param> /// <param name="cancellationToken">A cancellation token.</param> /// <exception cref="System.ArgumentNullException"> /// <para><paramref name="options"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="contentType"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="content"/> is <c>null</c>.</para> /// </exception> /// <exception cref="System.OperationCanceledException"> /// The operation was canceled via the cancellation token. /// </exception> /// <exception cref="System.FormatException"> /// There was an error parsing the entity. /// </exception> /// <exception cref="System.IO.IOException"> /// An I/O error occurred. /// </exception> public static MimeEntity Load(ParserOptions options, ContentType contentType, Stream content, CancellationToken cancellationToken = default(CancellationToken)) { if (options == null) { throw new ArgumentNullException("options"); } if (contentType == null) { throw new ArgumentNullException("contentType"); } if (content == null) { throw new ArgumentNullException("content"); } var format = FormatOptions.Default.Clone(); format.NewLineFormat = NewLineFormat.Dos; var encoded = contentType.Encode(format, Encoding.UTF8); var header = string.Format("Content-Type:{0}\r\n", encoded); var chained = new ChainedStream(); chained.Add(new MemoryStream(Encoding.UTF8.GetBytes(header), false)); chained.Add(content); return(Load(options, chained, cancellationToken)); }
public static MimeMessage ParseMessage(Stream inputStream, HTTPHeaders headers, CancellationToken cancellationToken) { if (inputStream == null || inputStream == Stream.Null) { return(null); } var headerArray = headers.ToArray(); if (IsMimeMessage(headerArray) == false) { return(null); } string headerString = String.Join("\r\n", headerArray.Select(h => $"{h.Name}: {h.Value}")); try { using (ChainedStream streamWithHeaders = new ChainedStream()) { streamWithHeaders.Add(new MemoryStream(Encoding.UTF8.GetBytes(headerString)), false); streamWithHeaders.Add(inputStream, false); var parser = new MimeKit.MimeParser(streamWithHeaders); return(parser.ParseMessage(cancellationToken)); } } catch (FormatException) { return(null); } }
public void TestStreamArguments() { using (var stream = new MeasuringStream()) AssertStreamArguments(stream); using (var stream = new MemoryBlockStream()) AssertStreamArguments(stream); using (var memory = new MemoryStream()) { Assert.Throws <ArgumentNullException> (() => new FilteredStream(null)); using (var stream = new FilteredStream(memory)) AssertStreamArguments(stream); } using (var memory = new MemoryStream()) { Assert.Throws <ArgumentNullException> (() => new BoundStream(null, 0, 10, true)); Assert.Throws <ArgumentOutOfRangeException> (() => new BoundStream(memory, -1, 10, true)); Assert.Throws <ArgumentOutOfRangeException> (() => new BoundStream(memory, 5, 1, true)); using (var stream = new BoundStream(memory, 0, -1, true)) AssertStreamArguments(stream); } using (var memory = new MemoryStream()) { using (var stream = new ChainedStream()) { stream.Add(memory); Assert.Throws <ArgumentNullException> (() => stream.Add(null)); AssertStreamArguments(stream); } } }
private Stream EncryptData(Stream secretStream, SymmetricAlgorithm algorithm) { Stream encryptedStream = CreateVirtualStreamOf(secretStream); var cryptoStream = new CryptoStream(encryptedStream, algorithm.CreateEncryptor(), CryptoStreamMode.Write); CipherMode origMode = algorithm.Mode; PaddingMode origPadding = algorithm.Padding; try { algorithm.Mode = Mode; algorithm.Padding = Padding; secretStream.CopyTo(cryptoStream); } finally { cryptoStream.FlushFinalBlock(); algorithm.Mode = origMode; algorithm.Padding = origPadding; } encryptedStream.Position = 0; if (Mode != CipherMode.ECB) { var chainedStream = new ChainedStream(); chainedStream.Add(new MemoryStream(algorithm.IV)); chainedStream.Add(encryptedStream); encryptedStream = chainedStream; } return(encryptedStream); }
private static async Task <Multipart> ReadMultipartAsync(HttpContent content, CancellationToken ct) { var responseStream = await content .ReadAsStreamAsync(); var headerStream = new MemoryStream(); using (var headerWriter = new StreamWriter(headerStream, new UTF8Encoding(false), 1000, true) { NewLine = "\r\n", }) { foreach (var contentHeader in content.Headers) { var line = $"{contentHeader.Key}: {string.Join(", ", contentHeader.Value)}"; await headerWriter.WriteLineAsync(line); } await headerWriter.WriteLineAsync(); } headerStream.Position = 0; using (var input = new ChainedStream()) { input.Add(headerStream); input.Add(responseStream, true); var multipart = MimeEntity.Load(input, ct); return(Assert.IsType <Multipart>(multipart)); } }
/// <summary> /// Asynchronously deserializes the given <paramref name="input"/> stream to an <see cref="AS4Message"/> model. /// </summary> /// <param name="input">The source stream from where the message should be read.</param> /// <param name="contentType">The content type required to correctly deserialize the message into different MIME parts.</param> /// <param name="cancellation">The token to control the cancellation of the deserialization.</param> public async Task <AS4Message> DeserializeAsync( Stream input, string contentType, CancellationToken cancellation = default(CancellationToken)) { if (input == null) { throw new ArgumentNullException(nameof(input)); } if (contentType == null) { throw new ArgumentNullException(nameof(contentType)); } var memoryStream = new MemoryStream( Encoding.UTF8.GetBytes($"Content-Type: {contentType}\r\n\r\n")); var chainedStream = new ChainedStream(); chainedStream.Add(memoryStream, leaveOpen: false); chainedStream.Add(input, leaveOpen: true); try { return(await ParseStreamToAS4MessageAsync(chainedStream, contentType, cancellation).ConfigureAwait(false)); } finally { // Since the stream has been read, make sure that all // parts of the chained-stream are re-positioned to the // beginning of each stream. chainedStream.Position = 0; } }
public ChainedStreamTests() { var bytes = new byte[10 * 1024]; int position = 0; random = new Random(); random.NextBytes(bytes); // this is our master stream, all operations on the chained stream // should match the results on this stream master = new MemoryStream(bytes); backing = new MemoryStream(master.ToArray()); cbuf = new byte[4096]; mbuf = new byte[4096]; // make a handful of smaller streams based on master to chain together chained = new ChainedStream(); while (position < bytes.Length) { int n = Math.Min(bytes.Length - position, random.Next() % 4096); var stream = new BoundStream(backing, position, position + n, true); lengths.Add(n); position += n; chained.Add(new ReadOneByteStream(stream)); } }
public void Setup() { var bytes = new byte[10 * 1024]; int position = 0; random = new Random(); random.NextBytes(bytes); // this is our master stream, all operations on the chained stream // should match the results on this stream master = new MemoryStream(bytes); cbuf = new byte[4096]; mbuf = new byte[4096]; // make a handful of smaller streams based on master to chain together chained = new ChainedStream(); while (position < bytes.Length) { int n = Math.Min(bytes.Length - position, random.Next() % 4096); var segment = new byte[n]; Buffer.BlockCopy(bytes, position, segment, 0, n); lengths.Add(n); position += n; chained.Add(new ReadOneByteStream(new MemoryStream(segment))); } }
public void TestStreamArguments() { using (var stream = new MeasuringStream()) AssertStreamArguments(stream); using (var stream = new MemoryBlockStream()) AssertStreamArguments(stream); using (var memory = new MemoryStream()) { using (var stream = new FilteredStream(memory)) AssertStreamArguments(stream); } using (var memory = new MemoryStream()) { using (var stream = new BoundStream(memory, 0, -1, true)) AssertStreamArguments(stream); } using (var memory = new MemoryStream()) { using (var stream = new ChainedStream()) { stream.Add(memory); AssertStreamArguments(stream); } } }
/// <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> /// Joins the specified message/partial parts into the complete message. /// </summary> /// <remarks> /// Combines all of the message/partial fragments into its original, /// complete, message. /// </remarks> /// <returns>The re-combined message.</returns> /// <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> /// <exception cref="System.ArgumentException"> /// <para>The last partial does not have a Total.</para> /// <para>-or-</para> /// <para>The number of partials provided does not match the expected count.</para> /// <para>-or-</para> /// <para>One or more partials is missing.</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("The last partial does not have a Total.", "partials"); } int total = parts[parts.Count - 1].Total.Value; if (parts.Count != total) { throw new ArgumentException("The number of partials provided does not match the expected count.", "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("One or more partials is missing.", "partials"); } var content = parts[i].ContentObject; chained.Add(content.Open()); } var parser = new MimeParser(options, chained); return(parser.ParseMessage()); } }
public void TestGetSetTimeouts() { using (var chained = new ChainedStream()) { chained.Add(new TimeoutStream()); Assert.Throws <InvalidOperationException> (() => { int x = chained.ReadTimeout; }); Assert.Throws <InvalidOperationException> (() => { int x = chained.WriteTimeout; }); Assert.Throws <InvalidOperationException> (() => chained.ReadTimeout = 5); Assert.Throws <InvalidOperationException> (() => chained.WriteTimeout = 5); } }
public void TestChainedHeadersAndContent() { var buf = Encoding.ASCII.GetBytes("Content-Type: text/plain\r\n\r\n"); var headers = new MemoryStream(); var content = new MemoryStream(); headers.Write(buf, 0, buf.Length); headers.Position = 0; buf = Encoding.ASCII.GetBytes("Hello, world!\r\n"); content.Write(buf, 0, buf.Length); content.Position = 0; using (var chained = new ChainedStream()) { chained.Add(headers); chained.Add(content); var entity = MimeEntity.Load(chained, true) as TextPart; Assert.AreEqual("Hello, world!" + Environment.NewLine, entity.Text); } }
public void TestCanReadWriteSeek() { var buffer = new byte[1024]; using (var chained = new ChainedStream()) { chained.Add(new CanReadWriteSeekStream(true, false, false, false)); Assert.IsTrue(chained.CanRead); Assert.IsFalse(chained.CanWrite); Assert.IsFalse(chained.CanSeek); Assert.IsFalse(chained.CanTimeout); Assert.Throws <NotImplementedException> (() => chained.Read(buffer, 0, buffer.Length)); Assert.Throws <NotSupportedException> (() => chained.Write(buffer, 0, buffer.Length)); Assert.Throws <NotSupportedException> (() => chained.Seek(0, SeekOrigin.End)); } using (var chained = new ChainedStream()) { chained.Add(new CanReadWriteSeekStream(false, true, false, false)); Assert.IsFalse(chained.CanRead); Assert.IsTrue(chained.CanWrite); Assert.IsFalse(chained.CanSeek); Assert.IsFalse(chained.CanTimeout); Assert.Throws <NotSupportedException> (() => chained.Read(buffer, 0, buffer.Length)); Assert.Throws <NotImplementedException> (() => chained.Write(buffer, 0, buffer.Length)); Assert.Throws <NotSupportedException> (() => chained.Seek(0, SeekOrigin.End)); } using (var chained = new ChainedStream()) { chained.Add(new CanReadWriteSeekStream(false, false, true, false)); Assert.IsFalse(chained.CanRead); Assert.IsFalse(chained.CanWrite); Assert.IsTrue(chained.CanSeek); Assert.IsFalse(chained.CanTimeout); Assert.Throws <NotSupportedException> (() => chained.Read(buffer, 0, buffer.Length)); Assert.Throws <NotSupportedException> (() => chained.Write(buffer, 0, buffer.Length)); Assert.Throws <NotImplementedException> (() => chained.Seek(0, SeekOrigin.End)); } }