diff options
Diffstat (limited to 'Crypto/src/openpgp/PgpObjectFactory.cs')
-rw-r--r-- | Crypto/src/openpgp/PgpObjectFactory.cs | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/Crypto/src/openpgp/PgpObjectFactory.cs b/Crypto/src/openpgp/PgpObjectFactory.cs new file mode 100644 index 000000000..c5c6fcb68 --- /dev/null +++ b/Crypto/src/openpgp/PgpObjectFactory.cs @@ -0,0 +1,143 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Bcpg.OpenPgp +{ + /// <remarks> + /// General class for reading a PGP object stream. + /// <p> + /// Note: if this class finds a PgpPublicKey or a PgpSecretKey it + /// will create a PgpPublicKeyRing, or a PgpSecretKeyRing for each + /// key found. If all you are trying to do is read a key ring file use + /// either PgpPublicKeyRingBundle or PgpSecretKeyRingBundle.</p> + /// </remarks> + public class PgpObjectFactory + { + private readonly BcpgInputStream bcpgIn; + + public PgpObjectFactory( + Stream inputStream) + { + this.bcpgIn = BcpgInputStream.Wrap(inputStream); + } + + public PgpObjectFactory( + byte[] bytes) + : this(new MemoryStream(bytes, false)) + { + } + + /// <summary>Return the next object in the stream, or null if the end is reached.</summary> + /// <exception cref="IOException">On a parse error</exception> + public PgpObject NextPgpObject() + { + PacketTag tag = bcpgIn.NextPacketTag(); + + if ((int) tag == -1) return null; + + switch (tag) + { + case PacketTag.Signature: + { + IList l = Platform.CreateArrayList(); + + while (bcpgIn.NextPacketTag() == PacketTag.Signature) + { + try + { + l.Add(new PgpSignature(bcpgIn)); + } + catch (PgpException e) + { + throw new IOException("can't create signature object: " + e); + } + } + + PgpSignature[] sigs = new PgpSignature[l.Count]; + for (int i = 0; i < l.Count; ++i) + { + sigs[i] = (PgpSignature)l[i]; + } + return new PgpSignatureList(sigs); + } + case PacketTag.SecretKey: + try + { + return new PgpSecretKeyRing(bcpgIn); + } + catch (PgpException e) + { + throw new IOException("can't create secret key object: " + e); + } + case PacketTag.PublicKey: + return new PgpPublicKeyRing(bcpgIn); + // TODO Make PgpPublicKey a PgpObject or return a PgpPublicKeyRing +// case PacketTag.PublicSubkey: +// return PgpPublicKeyRing.ReadSubkey(bcpgIn); + case PacketTag.CompressedData: + return new PgpCompressedData(bcpgIn); + case PacketTag.LiteralData: + return new PgpLiteralData(bcpgIn); + case PacketTag.PublicKeyEncryptedSession: + case PacketTag.SymmetricKeyEncryptedSessionKey: + return new PgpEncryptedDataList(bcpgIn); + case PacketTag.OnePassSignature: + { + IList l = Platform.CreateArrayList(); + + while (bcpgIn.NextPacketTag() == PacketTag.OnePassSignature) + { + try + { + l.Add(new PgpOnePassSignature(bcpgIn)); + } + catch (PgpException e) + { + throw new IOException("can't create one pass signature object: " + e); + } + } + + PgpOnePassSignature[] sigs = new PgpOnePassSignature[l.Count]; + for (int i = 0; i < l.Count; ++i) + { + sigs[i] = (PgpOnePassSignature)l[i]; + } + return new PgpOnePassSignatureList(sigs); + } + case PacketTag.Marker: + return new PgpMarker(bcpgIn); + case PacketTag.Experimental1: + case PacketTag.Experimental2: + case PacketTag.Experimental3: + case PacketTag.Experimental4: + return new PgpExperimental(bcpgIn); + } + + throw new IOException("unknown object in stream " + bcpgIn.NextPacketTag()); + } + + [Obsolete("Use NextPgpObject() instead")] + public object NextObject() + { + return NextPgpObject(); + } + + /// <summary> + /// Return all available objects in a list. + /// </summary> + /// <returns>An <c>IList</c> containing all objects from this factory, in order.</returns> + public IList AllPgpObjects() + { + IList result = Platform.CreateArrayList(); + PgpObject pgpObject; + while ((pgpObject = NextPgpObject()) != null) + { + result.Add(pgpObject); + } + return result; + } + } +} |