Crypt::OpenPGP::Compressed - Compressed data packets


Crypt-OpenPGP documentation Contained in the Crypt-OpenPGP distribution.

Index


Code Index:

NAME

Top

Crypt::OpenPGP::Compressed - Compressed data packets

SYNOPSIS

Top

    use Crypt::OpenPGP::Compressed;

    my $data = 'serialized openpgp packets';
    my $cdata = Crypt::OpenPGP::Compressed->new( Data => $data );
    my $serialized = $cdata->save;

DESCRIPTION

Top

Crypt::OpenPGP::Compressed implements compressed data packets, providing both compression and decompression functionality, for all supported compression algorithms (Zlib and ZIP). This class uses Compress::Zlib for all compression/decompression needs for both algorithms: ZIP is simply Zlib with a different setting for the WindowBits parameter.

Decompressing a compressed data packet should always yield a stream of valid PGP packets (which you can then parse using Crypt::OpenPGP::PacketFactory). Similarly, when compressing a packet the input data should be a stream of packets.

USAGE

Top

Crypt::OpenPGP::Compressed->new( %arg )

Creates a new compressed data packet object and returns that object. If there are no arguments in %arg, the object is created with an empty compressed data container; this is used, for example, in parse (below), to create an empty packet which is then filled with the data in the buffer.

If you wish to initialize a non-empty object, %arg can contain:

* Data

A block of octets that make up the data that you wish to compress. As mentioned above, the data to compress should always be a stream of valid PGP packets (saved using Crypt::OpenPGP::PacketFactory::save).

This argument is required (for a non-empty object).

* Alg

The name (or ID) of a supported PGP compression algorithm. Valid names are Zlib and ZIP.

This argument is optional; by default Crypt::OpenPGP::Compressed will use ZIP.

$cdata->save

Returns the serialized compressed data packet, which consists of a one-octet compression algorithm ID, followed by the compressed data.

Crypt::OpenPGP::Compressed->parse($buffer)

Given $buffer, a Crypt::OpenPGP::Buffer object holding (or with offset pointing to) a compressed data packet, returns a new Crypt::OpenPGP::Compressed object, initialized with the data from the buffer.

$cdata->decompress

Decompresses the compressed data in the Crypt::OpenPGP::Compressed object $cdata and returns the decompressed data.

AUTHOR & COPYRIGHTS

Top

Please see the Crypt::OpenPGP manpage for author, copyright, and license information.


Crypt-OpenPGP documentation Contained in the Crypt-OpenPGP distribution.

package Crypt::OpenPGP::Compressed;
use strict;

use Compress::Zlib;
use Crypt::OpenPGP::Buffer;
use Crypt::OpenPGP::Constants qw( DEFAULT_COMPRESS );
use Crypt::OpenPGP::ErrorHandler;
use base qw( Crypt::OpenPGP::ErrorHandler );

use vars qw( %ALG %ALG_BY_NAME );
%ALG = ( 1 => 'ZIP', 2 => 'Zlib' );
%ALG_BY_NAME = map { $ALG{$_} => $_ } keys %ALG;

sub alg {
    return $_[0]->{__alg} if ref($_[0]);
    $ALG{$_[1]} || $_[1];
}

sub alg_id {
    return $_[0]->{__alg_id} if ref($_[0]);
    $ALG_BY_NAME{$_[1]} || $_[1];
}

sub new {
    my $comp = bless { }, shift;
    $comp->init(@_);
}

sub init {
    my $comp = shift;
    my %param = @_;
    if (my $data = $param{Data}) {
        my $alg = $param{Alg} || DEFAULT_COMPRESS;
        $alg = $ALG{$alg} || $alg;
        $comp->{__alg} = $alg;
        $comp->{__alg_id} = $ALG_BY_NAME{$alg};
        my %args;
        if ($comp->{__alg_id} == 1) {
            %args = (-WindowBits => -13, -MemLevel => 8);
        }
        my($d, $status, $compressed);
        ($d, $status) = deflateInit(\%args);
        return (ref $comp)->error("Zlib deflateInit error: $status")
            unless $status == Compress::Zlib::Z_OK();
        {
            my($output, $out);
            ($output, $status) = $d->deflate($data);
            last unless $status == Compress::Zlib::Z_OK();
            ($out, $status) = $d->flush();
            last unless $status == Compress::Zlib::Z_OK();
            $compressed = $output . $out;
        }
        return (ref $comp)->error("Zlib deflation error: $status")
            unless defined $compressed;
        $comp->{data} = $compressed;
    }
    $comp;
}

sub parse {
    my $class = shift;
    my($buf) = @_;
    my $comp = $class->new;
    $comp->{__alg_id} = $buf->get_int8;
    $comp->{__alg} = $ALG{ $comp->{__alg_id} };
    $comp->{data} = $buf->get_bytes($buf->length - $buf->offset);
    $comp;
}

sub save {
    my $comp = shift;
    my $buf = Crypt::OpenPGP::Buffer->new;
    $buf->put_int8($comp->{__alg_id});
    $buf->put_bytes($comp->{data});
    $buf->bytes;
}

sub decompress {
    my $comp = shift;
    my %args;
    if ($comp->{__alg_id} == 1) {
        %args = (-WindowBits => -13);
    }
    my($i, $status, $out);
    ($i, $status) = inflateInit(\%args);
    return $comp->error("Zlib inflateInit error: $status")
        unless $status == Compress::Zlib::Z_OK();
    ($out, $status) = $i->inflate($comp->{data});
    return $comp->error("Zlib inflate error: $status")
        unless defined $out;
    $out;
}

1;
__END__