<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">package PGP::Keyring;

use strict;

use Carp;
use PGP::Unpackable;
use PGP::Packet;
use PGP::Certificate;

sub new {
    my ($classname, $strref) = @_;

    bless {
	"ring" =&gt; new PGP::Unpackable($strref),
	"nextpubkey" =&gt; undef,
    }, $classname;
}

sub NextPacket {
    my ($self) = @_;
    
    PGP::Packet::next($self-&gt;{"ring"});
}

sub NextCert {
    my ($self) = @_;
    my @packets;

    if ($self-&gt;{"nextpubkey"}) {
	# this case happens when on a second or greater call to NextCert

	push(@packets, $self-&gt;{"nextpubkey"});
	$self-&gt;{"nextpubkey"} = undef;
    } elsif ($self-&gt;{"ring"}-&gt;remaining() == 0) {
	# this case happens when the keyring is empty on the first call,
	# or after the last key has been returned.

	return(undef);
    } else {
	# this case is for the normal first call

	my $packet = PGP::Packet::next($self-&gt;{"ring"});

	if ($packet-&gt;ctag != 6) {
	    confess "first packet is not a public key";
	}
	push(@packets, $packet);
    }

    while ($self-&gt;{"ring"}-&gt;remaining() &gt; 0) {
	my $packet = PGP::Packet::next($self-&gt;{"ring"});

	if ($packet-&gt;ctag == 6) {
	    $self-&gt;{"nextpubkey"} = $packet;
	    last;
	} else {
	    push(@packets, $packet);
	}
    }

    new PGP::Certificate(\@packets);
}

1;

# XXX Someday, use a state machine, where state is next thing to read
# (length):

# - ptag (1 byte)
# - old length, type = 0 (1 byte)
# - old length, type = 1 (2 bytes)
# - old length, type = 2 (4 bytes)
# - old body (next frag length from state)
# - new lbyte (1 byte)
# - new 2-byte length, octet 2 (1 byte)
# - new 5-byte length, length word (4 bytes)
# - new body fragment (next frag length from state)
#
# stuff to carry between states
# - unparsed octets
# - ctag
# - next fragment length
# - partial $key
# - new partial body and length (after new indefinite block)

# But for now, assume the keyring is in memory.  For initialization
# from Big Files, the caller can use Mmap, otherwise, keyrings from
# the network are likely to be reasonably sized and can be read in.
# Eventually, this may turn into a state machine, but it will be less
# readable.

# this also assumes that no individual key or packet will be
# particularly large, especially partial body length encoded packets,
# because returned keys will not use references.
</pre></body></html>