Restore SEBPatch
This commit is contained in:
140
SafeExamBrowser.Configuration/SubStream.cs
Normal file
140
SafeExamBrowser.Configuration/SubStream.cs
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (c) 2024 ETH Zürich, IT Services
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace SafeExamBrowser.Configuration
|
||||
{
|
||||
/// <summary>
|
||||
/// A read-only wrapper for a subsection of another, larger stream.
|
||||
/// </summary>
|
||||
internal class SubStream : Stream
|
||||
{
|
||||
private long length;
|
||||
private long offset;
|
||||
private Stream original;
|
||||
|
||||
public override bool CanRead => original.CanRead;
|
||||
public override bool CanSeek => original.CanSeek;
|
||||
public override bool CanWrite => false;
|
||||
public override long Length => length;
|
||||
public override long Position { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new wrapper for the specified subsection of the given stream.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
///
|
||||
/// Below an example of a subsection within a stream:
|
||||
///
|
||||
/// +==============+==============================================================+==============================+
|
||||
/// | ... |####################### subsection ###########################| ... |
|
||||
/// +==============+==============================================================+==============================+
|
||||
/// ^ ^ ^ ^
|
||||
/// | | | |
|
||||
/// | + offset + length |
|
||||
/// | |
|
||||
/// + start of original end of original +
|
||||
///
|
||||
/// </remarks>
|
||||
/// <exception cref="ArgumentException">In case the original stream does not support <see cref="Stream.CanRead"/>.</exception>
|
||||
/// <exception cref="ArgumentException">In case the original stream does not support <see cref="Stream.CanSeek"/>.</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">In case the specified subsection is outside the bounds of the original stream.</exception>
|
||||
public SubStream(Stream original, long offset, long length)
|
||||
{
|
||||
this.original = original;
|
||||
this.offset = offset;
|
||||
this.length = length;
|
||||
|
||||
if (!original.CanRead)
|
||||
{
|
||||
throw new ArgumentException("The original stream must support reading!", nameof(original));
|
||||
}
|
||||
|
||||
if (!original.CanSeek)
|
||||
{
|
||||
throw new ArgumentException("The original stream must support seeking!", nameof(original));
|
||||
}
|
||||
|
||||
if (original.Length < offset + length || offset < 0 || length < 1)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException($"Specified subsection is outside the bounds of the original stream!");
|
||||
}
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
var originalPosition = original.Position;
|
||||
|
||||
if (Position < 0 || Position >= Length)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (Position + count >= Length)
|
||||
{
|
||||
count = Convert.ToInt32(Length - Position);
|
||||
}
|
||||
|
||||
original.Seek(this.offset + Position, SeekOrigin.Begin);
|
||||
|
||||
var bytesRead = original.Read(buffer, offset, count);
|
||||
|
||||
Position += bytesRead;
|
||||
original.Seek(originalPosition, SeekOrigin.Begin);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
public override int ReadByte()
|
||||
{
|
||||
if (Position < 0 || Position >= Length)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return base.ReadByte();
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
switch (origin)
|
||||
{
|
||||
case SeekOrigin.Begin:
|
||||
Position = offset;
|
||||
break;
|
||||
case SeekOrigin.Current:
|
||||
Position += offset;
|
||||
break;
|
||||
case SeekOrigin.End:
|
||||
Position = length + offset;
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException($"Seeking from position '{origin}' is not implemented!");
|
||||
}
|
||||
|
||||
return Position;
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user