Index: samples/NetVips.Samples/Samples/Stream.cs
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/samples/NetVips.Samples/Samples/Stream.cs b/samples/NetVips.Samples/Samples/Stream.cs
--- a/samples/NetVips.Samples/Samples/Stream.cs (revision a47d04ffddce3d6d70f900416bdf336466427555)
+++ b/samples/NetVips.Samples/Samples/Stream.cs (date 1605754129319)
@@ -1,3 +1,6 @@
+using System.Security;
+using NetVips.Samples.MS.Internal.Documents.Application;
+
namespace NetVips.Samples
{
using System;
@@ -12,16 +15,68 @@
public string Execute(string[] args)
{
- using (var input = File.OpenRead(Filename))
+ using (var file = File.OpenRead(Filename))
{
- var image = Image.NewFromStream(input, access: Enums.Access.Sequential);
- Console.WriteLine(image.ToString());
+ using (var buffered = new BufferedStream(file, 8092))
+ {
+ byte[] dataToSend = new byte[8092];
+ buffered.Read(dataToSend, 0, 8092);
+ buffered.Position = 0;
+ using (var input = new StreamLengthDecorator(buffered))
+ {
+ var image = Image.NewFromStream(input, access: Enums.Access.Sequential);
+ Console.WriteLine(image.ToString());
- using var output = File.OpenWrite("stream.png");
- image.WriteToStream(output, ".png");
+ using var output = File.OpenWrite("stream.png");
+ image.WriteToStream(output, ".png");
+ }
+ }
}
return "See stream.png";
}
}
+
+ public class StreamLengthDecorator : StreamProxy
+ {
+ private string _prefix;
+
+ public StreamLengthDecorator(System.IO.Stream stream, string prefix = "")
+ : base(stream)
+ {
+ _prefix = prefix;
+ }
+
+ protected override void BeforeRead(int n)
+ {
+ Console.WriteLine($"{_prefix}-> {n} bytes");
+ }
+
+ protected override void AfterRead(int n)
+ {
+ Console.WriteLine($"{_prefix}<- {n} bytes");
+ }
+ }
+
+ public class PartialReturnDecorator : StreamProxy
+ {
+ private int min, max;
+
+ public PartialReturnDecorator(System.IO.Stream stream, int min = 4096, int max = 5173)
+ : base(stream)
+ {
+ this.min = min;
+ this.max = max;
+ }
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ if (count > min && count > max)
+ {
+ return base.Read(buffer, offset, max);
+ }
+
+ return base.Read(buffer, offset, count);
+ }
+ }
}
\ No newline at end of file
Index: samples/NetVips.Samples/Samples/StreamProxy.cs
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/samples/NetVips.Samples/Samples/StreamProxy.cs b/samples/NetVips.Samples/Samples/StreamProxy.cs
new file mode 100644
--- /dev/null (date 1605754118436)
+++ b/samples/NetVips.Samples/Samples/StreamProxy.cs (date 1605754118436)
@@ -0,0 +1,270 @@
+namespace NetVips.Samples
+{
+//
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+//
+// Implements the Proxy pattern from Design Patterns for Stream. The intended
+// usage is to control access to the Stream; specifically to allow one to
+// replace the underlying stream. The StreamProxy can also ensure, if
+// desired, that the underlying stream is readonly.
+//
+//
+// History:
+// 08/28/2005: [....]: Initial implementation.
+//-----------------------------------------------------------------------------
+
+ using System;
+ using System.IO;
+ using System.Security;
+
+ namespace MS.Internal.Documents.Application
+ {
+ ///
+ /// Implements the Proxy pattern from Design Patterns for Stream. The intended
+ /// usage is to control access to the Stream; specifically to allow one to
+ /// replace the underlying stream. The StreamProxy can also ensure, if
+ /// desired, that the underlying stream is readonly.
+ ///
+ public class StreamProxy : System.IO.Stream
+ {
+ private System.IO.Stream _proxy;
+ private bool _isTargetReadOnly;
+
+ #region Constructors
+
+ //-------------------------------------------------------------------------
+ // Constructors
+ //-------------------------------------------------------------------------
+
+ ///
+ /// Will construct a StreamProxy backed by the specified stream and leave
+ /// the target modifiable.
+ ///
+ /// The stream that is backing the proxy.
+ ///
+ internal StreamProxy(System.IO.Stream targetOfProxy)
+ : this(targetOfProxy, false)
+ {
+ }
+
+ ///
+ /// Will construct a StreamProxy backed by the specified stream and make
+ /// the target read-only if so specified.
+ ///
+ /// The stream that is backing the proxy.
+ ///
+ /// Whether or not the target should be set
+ /// to read-only.
+ ///
+ /// Critical
+ /// 1) Setting critical for set values _proxy & _isTargetReadOnly.
+ /// TreatAsSafe
+ /// 1) We only want to ensure that the user cannot circumvent using either
+ /// the constructor or the Target property to set the proxy. Creating
+ /// the StreamProxy itself is a safe operation.
+ ///
+ [SecurityCritical, SecurityTreatAsSafe]
+ internal StreamProxy(System.IO.Stream targetOfProxy, bool isTargetReadOnly)
+ {
+ _proxy = targetOfProxy;
+ _isTargetReadOnly = isTargetReadOnly;
+ }
+
+ #endregion Constructors
+
+ #region Stream Overrides
+
+ //--------------------------------------------------------------------------
+ // Stream Overrides
+ //-------------------------------------------------------------------------
+
+ ///
+ ///
+ ///
+ public override bool CanRead => _proxy.CanRead;
+
+ ///
+ ///
+ ///
+ public override bool CanSeek
+ {
+ get { return _proxy.CanSeek; }
+ }
+
+ ///
+ ///
+ ///
+ public override bool CanTimeout
+ {
+ get { return _proxy.CanTimeout; }
+ }
+
+ ///
+ ///
+ ///
+ public override bool CanWrite
+ {
+ get { return _proxy.CanWrite; }
+ }
+
+ ///
+ ///
+ ///
+ public override void Close()
+ {
+ _proxy.Close();
+ }
+
+ ///
+ ///
+ ///
+ public override void Flush()
+ {
+ _proxy.Flush();
+ }
+
+ ///
+ ///
+ ///
+ public override long Length
+ {
+ get { return _proxy.Length; }
+ }
+
+ ///
+ ///
+ ///
+ public override long Position
+ {
+ get { return _proxy.Position; }
+ set { _proxy.Position = value; }
+ }
+
+ ///
+ ///
+ ///
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ BeforeRead(count);
+ int readBytes = _proxy.Read(buffer, offset, count);
+ AfterRead(readBytes);
+ return readBytes;
+ }
+
+ ///
+ ///
+ ///
+ public override int ReadTimeout
+ {
+ get { return _proxy.ReadTimeout; }
+ set { _proxy.ReadTimeout = value; }
+ }
+
+ ///
+ ///
+ ///
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ return _proxy.Seek(offset, origin);
+ }
+
+ ///
+ ///
+ ///
+ public override void SetLength(long value)
+ {
+ _proxy.SetLength(value);
+ }
+
+ ///
+ ///
+ ///
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ _proxy.Write(buffer, offset, count);
+ }
+
+ ///
+ /// Invoked by the read methods before the call is proxied.
+ ///
+ /// number of bytes that the caller asked to be read
+ protected virtual void BeforeRead(int n)
+ {
+ }
+
+ ///
+ /// Invoked by the read methods after the proxied call has returned successfully.
+ ///
+ /// number of bytes read, or -1 if the end of stream was reached
+ protected virtual void AfterRead(int n)
+ {
+ }
+
+ ///
+ ///
+ ///
+ public int WriteTimeout
+ {
+ get { return _proxy.WriteTimeout; }
+ set { _proxy.WriteTimeout = value; }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// Critical
+ /// 1) Setting critical for set value _proxy.
+ /// TreatAsSafe
+ /// 1) Setting to known safe value null.
+ ///
+ [SecurityCritical, SecurityTreatAsSafe]
+ protected void Dispose(bool disposing)
+ {
+ _proxy.Dispose();
+ try
+ {
+ // other operations like async methods in
+ // our base class call us, we need them to
+ // clean up before we release the proxy
+ base.Dispose(disposing);
+ }
+ finally
+ {
+ if (disposing && _proxy != null)
+ {
+ _proxy.Dispose();
+ _proxy = null;
+ }
+ }
+ }
+
+ #endregion Stream Overrides
+
+ #region Object Overrides
+
+ //--------------------------------------------------------------------------
+ // Object Overrides
+ //--------------------------------------------------------------------------
+
+ ///
+ ///
+ ///
+ public override int GetHashCode()
+ {
+ return _proxy.GetHashCode();
+ }
+
+ ///
+ ///
+ ///
+ public override bool Equals(object obj)
+ {
+ return _proxy.Equals(obj);
+ }
+
+ #endregion Object Overrides
+ }
+ }
+}
\ No newline at end of file
Index: samples/NetVips.Samples/Samples/NetworkStream.cs
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/samples/NetVips.Samples/Samples/NetworkStream.cs b/samples/NetVips.Samples/Samples/NetworkStream.cs
--- a/samples/NetVips.Samples/Samples/NetworkStream.cs (revision a47d04ffddce3d6d70f900416bdf336466427555)
+++ b/samples/NetVips.Samples/Samples/NetworkStream.cs (date 1605753994424)
@@ -9,18 +9,24 @@
public string Name => "Network stream";
public string Category => "Streaming";
- public const string Uri = "https://images.weserv.nl/zebra.jpg";
+ const string Uri =
+ "https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png";
public string Execute(string[] args)
{
using var web = new WebClient();
using (var stream = web.OpenRead(Uri))
{
- var image = Image.NewFromStream(stream, access: Enums.Access.Sequential);
- Console.WriteLine(image.ToString());
-
- using var output = File.OpenWrite("stream-network.jpg");
- image.WriteToStream(output, ".jpg");
+ using (var partialReturnDecorator = new PartialReturnDecorator(stream, 512, 3173))
+ {
+ using (var input = new StreamLengthDecorator(partialReturnDecorator))
+ {
+ var image = Image.NewFromStream(input, access: Enums.Access.Sequential);
+ Console.WriteLine(image.ToString());
+ using var output = File.OpenWrite("stream-network.jpg");
+ image.WriteToStream(output, ".jpg");
+ }
+ }
}
return "See stream-network.jpg";