BcpgInputStream
using Org.BouncyCastle.Utilities.IO;
using System;
using System.IO;
namespace Org.BouncyCastle.Bcpg
{
public class BcpgInputStream : BaseInputStream
{
private class PartialInputStream : BaseInputStream
{
private BcpgInputStream m_in;
private bool partial;
private int dataLength;
internal PartialInputStream(BcpgInputStream bcpgIn, bool partial, int dataLength)
{
m_in = bcpgIn;
this.partial = partial;
this.dataLength = dataLength;
}
public override int ReadByte()
{
do {
if (dataLength != 0) {
int num = m_in.ReadByte();
if (num < 0)
throw new EndOfStreamException("Premature end of stream in PartialInputStream");
dataLength--;
return num;
}
} while (partial && ReadPartialDataLength() >= 0);
return -1;
}
public override int Read(byte[] buffer, int offset, int count)
{
Streams.ValidateBufferArguments(buffer, offset, count);
do {
if (dataLength != 0) {
int count2 = (dataLength > count || dataLength < 0) ? count : dataLength;
int num = m_in.Read(buffer, offset, count2);
if (num < 1)
throw new EndOfStreamException("Premature end of stream in PartialInputStream");
dataLength -= num;
return num;
}
} while (partial && ReadPartialDataLength() >= 0);
return 0;
}
public override int Read(Span<byte> buffer)
{
do {
if (dataLength != 0) {
int length = buffer.Length;
int length2 = (dataLength > length || dataLength < 0) ? length : dataLength;
int num = m_in.Read(buffer.Slice(0, length2));
if (num < 1)
throw new EndOfStreamException("Premature end of stream in PartialInputStream");
dataLength -= num;
return num;
}
} while (partial && ReadPartialDataLength() >= 0);
return 0;
}
private int ReadPartialDataLength()
{
int num = m_in.ReadByte();
if (num < 0)
return -1;
partial = false;
if (num < 192)
dataLength = num;
else if (num <= 223) {
dataLength = (num - 192 << 8) + m_in.ReadByte() + 192;
} else if (num == 255) {
dataLength = ((m_in.ReadByte() << 24) | (m_in.ReadByte() << 16) | (m_in.ReadByte() << 8) | m_in.ReadByte());
} else {
partial = true;
dataLength = 1 << (num & 31);
}
return 0;
}
}
private Stream m_in;
private bool next;
private int nextB;
internal static BcpgInputStream Wrap(Stream inStr)
{
BcpgInputStream bcpgInputStream = inStr as BcpgInputStream;
if (bcpgInputStream != null)
return bcpgInputStream;
return new BcpgInputStream(inStr);
}
private BcpgInputStream(Stream inputStream)
{
m_in = inputStream;
}
public override int ReadByte()
{
if (next) {
next = false;
return nextB;
}
return m_in.ReadByte();
}
public override int Read(byte[] buffer, int offset, int count)
{
if (!next)
return m_in.Read(buffer, offset, count);
Streams.ValidateBufferArguments(buffer, offset, count);
if (nextB < 0)
return 0;
buffer[offset] = (byte)nextB;
next = false;
return 1;
}
public override int Read(Span<byte> buffer)
{
if (!next)
return m_in.Read(buffer);
if (nextB < 0)
return 0;
buffer[0] = (byte)nextB;
next = false;
return 1;
}
public byte[] ReadAll()
{
return Streams.ReadAll(this);
}
public void ReadFully(byte[] buffer, int offset, int count)
{
if (Streams.ReadFully(this, buffer, offset, count) < count)
throw new EndOfStreamException();
}
public void ReadFully(byte[] buffer)
{
ReadFully(buffer, 0, buffer.Length);
}
public void ReadFully(Span<byte> buffer)
{
if (Streams.ReadFully(this, buffer) < buffer.Length)
throw new EndOfStreamException();
}
public PacketTag NextPacketTag()
{
if (!next) {
try {
nextB = m_in.ReadByte();
} catch (EndOfStreamException) {
nextB = -1;
}
next = true;
}
if (nextB < 0)
return (PacketTag)nextB;
int num = nextB & 63;
if ((nextB & 64) == 0)
num >>= 2;
return (PacketTag)num;
}
public Packet ReadPacket()
{
int num = ReadByte();
if (num < 0)
return null;
if ((num & 128) == 0)
throw new IOException("invalid header encountered");
bool num2 = (num & 64) != 0;
PacketTag packetTag = PacketTag.Reserved;
int num3 = 0;
bool flag = false;
if (num2) {
packetTag = (PacketTag)(num & 63);
int num4 = ReadByte();
if (num4 < 192)
num3 = num4;
else if (num4 <= 223) {
int num5 = m_in.ReadByte();
num3 = (num4 - 192 << 8) + num5 + 192;
} else if (num4 == 255) {
num3 = ((m_in.ReadByte() << 24) | (m_in.ReadByte() << 16) | (m_in.ReadByte() << 8) | m_in.ReadByte());
} else {
flag = true;
num3 = 1 << (num4 & 31);
}
} else {
int num6 = num & 3;
packetTag = (PacketTag)((num & 63) >> 2);
switch (num6) {
case 0:
num3 = ReadByte();
break;
case 1:
num3 = ((ReadByte() << 8) | ReadByte());
break;
case 2:
num3 = ((ReadByte() << 24) | (ReadByte() << 16) | (ReadByte() << 8) | ReadByte());
break;
case 3:
flag = true;
break;
default:
throw new IOException("unknown length type encountered");
}
}
BcpgInputStream bcpgIn = (!((num3 == 0) & flag)) ? new BcpgInputStream(new BufferedStream(new PartialInputStream(this, flag, num3))) : this;
switch (packetTag) {
default:
if ((uint)(packetTag - 60) <= 3)
return new ExperimentalPacket(packetTag, bcpgIn);
break;
case PacketTag.Reserved:
return new InputStreamPacket(bcpgIn);
case PacketTag.PublicKeyEncryptedSession:
return new PublicKeyEncSessionPacket(bcpgIn);
case PacketTag.Signature:
return new SignaturePacket(bcpgIn);
case PacketTag.SymmetricKeyEncryptedSessionKey:
return new SymmetricKeyEncSessionPacket(bcpgIn);
case PacketTag.OnePassSignature:
return new OnePassSignaturePacket(bcpgIn);
case PacketTag.SecretKey:
return new SecretKeyPacket(bcpgIn);
case PacketTag.PublicKey:
return new PublicKeyPacket(bcpgIn);
case PacketTag.SecretSubkey:
return new SecretSubkeyPacket(bcpgIn);
case PacketTag.CompressedData:
return new CompressedDataPacket(bcpgIn);
case PacketTag.SymmetricKeyEncrypted:
return new SymmetricEncDataPacket(bcpgIn);
case PacketTag.Marker:
return new MarkerPacket(bcpgIn);
case PacketTag.LiteralData:
return new LiteralDataPacket(bcpgIn);
case PacketTag.Trust:
return new TrustPacket(bcpgIn);
case PacketTag.UserId:
return new UserIdPacket(bcpgIn);
case PacketTag.UserAttribute:
return new UserAttributePacket(bcpgIn);
case PacketTag.PublicSubkey:
return new PublicSubkeyPacket(bcpgIn);
case PacketTag.SymmetricEncryptedIntegrityProtected:
return new SymmetricEncIntegrityPacket(bcpgIn);
case PacketTag.ModificationDetectionCode:
return new ModDetectionCodePacket(bcpgIn);
case (PacketTag)15:
case (PacketTag)16:
break;
}
throw new IOException("unknown packet type encountered: " + packetTag.ToString());
}
public PacketTag SkipMarkerPackets()
{
PacketTag result;
while ((result = NextPacketTag()) == PacketTag.Marker) {
ReadPacket();
}
return result;
}
protected override void Dispose(bool disposing)
{
if (disposing)
m_in.Dispose();
base.Dispose(disposing);
}
}
}