BcpgInputStream
using Org.BouncyCastle.Utilities.IO;
using System.IO;
namespace Org.BouncyCastle.Bcpg
{
public class BcpgInputStream : BaseInputStream
{
private class PartialInputStream : BaseInputStream
{
private readonly Stream m_in;
private bool m_partial;
private uint m_dataLength;
internal PartialInputStream(Stream inStr, bool partial, uint dataLength)
{
m_in = inStr;
m_partial = partial;
m_dataLength = dataLength;
}
public override int ReadByte()
{
do {
if (m_dataLength != 0) {
int num = m_in.ReadByte();
if (num < 0)
throw new EndOfStreamException("Premature end of stream in PartialInputStream");
m_dataLength--;
return num;
}
} while (m_partial && ReadPartialDataLength());
return -1;
}
public override int Read(byte[] buffer, int offset, int count)
{
Streams.ValidateBufferArguments(buffer, offset, count);
do {
if (m_dataLength != 0) {
int count2 = ((uint)count < m_dataLength) ? count : ((int)m_dataLength);
int num = m_in.Read(buffer, offset, count2);
if (num < 1)
throw new EndOfStreamException("Premature end of stream in PartialInputStream");
m_dataLength -= (uint)num;
return num;
}
} while (m_partial && ReadPartialDataLength());
return 0;
}
private bool ReadPartialDataLength()
{
StreamUtilities.StreamFlags flags;
uint dataLength = StreamUtilities.ReadBodyLen(m_in, out flags);
if (flags.HasFlag(StreamUtilities.StreamFlags.Eof)) {
m_partial = false;
m_dataLength = 0;
return false;
}
m_partial = flags.HasFlag(StreamUtilities.StreamFlags.Partial);
m_dataLength = dataLength;
return true;
}
}
private readonly 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 byte[] ReadAll()
{
return Streams.ReadAll(this);
}
public void ReadFully(byte[] buffer, int offset, int count)
{
StreamUtilities.RequireBytes(this, buffer, offset, count);
}
public void ReadFully(byte[] buffer)
{
StreamUtilities.RequireBytes(this, buffer);
}
public byte RequireByte()
{
return StreamUtilities.RequireByte(this);
}
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;
bool flag = false;
uint num3;
if (num2) {
packetTag = (PacketTag)(num & 63);
num3 = StreamUtilities.RequireBodyLen(this, out StreamUtilities.StreamFlags streamFlags);
flag = streamFlags.HasFlag(StreamUtilities.StreamFlags.Partial);
} else {
int num4 = num & 3;
packetTag = (PacketTag)((num & 63) >> 2);
switch (num4) {
case 0:
num3 = StreamUtilities.RequireByte(this);
break;
case 1:
num3 = StreamUtilities.RequireUInt16BE(this);
break;
case 2:
num3 = StreamUtilities.RequireUInt32BE(this);
break;
case 3:
num3 = 0;
flag = true;
break;
default:
throw new IOException("unknown length type encountered");
}
}
BcpgInputStream bcpgIn = (!((num3 == 0) & flag)) ? new BcpgInputStream(new BufferedStream(new PartialInputStream(m_in, 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);
}
}
}