File Coverage

blib/lib/Crypt/OpenPGP/Message.pm
Criterion Covered Total %
statement 54 61 88.5
branch 10 16 62.5
condition 8 11 72.7
subroutine 10 10 100.0
pod 2 5 40.0
total 84 103 81.5


line stmt bran cond sub pod time code
1             package Crypt::OpenPGP::Message;
2 7     7   34 use strict;
  7         8  
  7         225  
3              
4 7     7   36 use Crypt::OpenPGP::Buffer;
  7         12  
  7         151  
5 7     7   30 use Crypt::OpenPGP::PacketFactory;
  7         9  
  7         154  
6 7     7   29 use Crypt::OpenPGP::ErrorHandler;
  7         11  
  7         178  
7 7     7   36 use base qw( Crypt::OpenPGP::ErrorHandler );
  7         18  
  7         5247  
8              
9             sub new {
10 57     57 1 663 my $class = shift;
11 57         142 my $msg = bless { }, $class;
12 57         201 $msg->init(@_);
13             }
14              
15             sub init {
16 57     57 0 104 my $msg = shift;
17 57         186 my %param = @_;
18 57         200 $msg->{is_packet_stream} = delete $param{IsPacketStream};
19 57         131 $msg->{pieces} = [];
20 57   50     213 $msg->{_data} = $param{Data} || '';
21 57 50 33     230 if (!$msg->{_data} && (my $file = $param{Filename})) {
22 0         0 local *FH;
23 0 0       0 open FH, $file or
24             return (ref $msg)->error("Can't open message $file: $!");
25 0         0 binmode FH;
26 0         0 { local $/; $msg->{_data} = <FH> }
  0         0  
  0         0  
27 0         0 close FH;
28             }
29 57 50       178 $msg->read or return;
30 57         277 $msg;
31             }
32              
33             sub read {
34 57     57 0 95 my $msg = shift;
35             my $data = $msg->{_data} or
36 57 50       178 return $msg->error("Message contains no data");
37 57         77 my $pt;
38 57 100 100     358 if (!$msg->{is_packet_stream} &&
39             $data =~ /-----BEGIN PGP SIGNED MESSAGE/) {
40 1         4 require Crypt::OpenPGP::Armour;
41 1         3 require Crypt::OpenPGP::Util;
42 1         4 require Crypt::OpenPGP::Plaintext;
43 1         12 my($head, $text, $sig) = $data =~
44             m!-----BEGIN PGP SIGNED MESSAGE-----(.*?\r?\n\r?\n)?(.+?)(-----BEGIN PGP SIGNATURE.*?END PGP SIGNATURE-----)!s;
45             ## In clear-signed messages, the line ending before the signature
46             ## is not considered part of the signed text.
47 1         5 $text =~ s!\r?\n$!!;
48 1         6 $pt = Crypt::OpenPGP::Plaintext->new(
49             Data => Crypt::OpenPGP::Util::dash_unescape($text),
50             Mode => 't',
51             );
52 1         2 $data = $sig;
53             }
54              
55 57 100 100     302 if (!$msg->{is_packet_stream} && $data =~ /^-----BEGIN PGP/m) {
56 5         24 require Crypt::OpenPGP::Armour;
57 5 50       25 my $rec = Crypt::OpenPGP::Armour->unarmour($data) or
58             return $msg->error("Unarmour failed: " .
59             Crypt::OpenPGP::Armour->errstr);
60 5         17 $data = $rec->{Data};
61             }
62 57         261 my $buf = Crypt::OpenPGP::Buffer->new;
63 57         610 $buf->append($data);
64 57         388 $msg->restore($buf);
65 57 100       553 push @{ $msg->{pieces} }, $pt if $pt;
  1         4  
66 57         248 1;
67             }
68              
69             sub restore {
70 57     57 0 84 my $msg = shift;
71 57         99 my($buf) = @_;
72 57         278 while (my $packet = Crypt::OpenPGP::PacketFactory->parse($buf)) {
73 93         133 push @{ $msg->{pieces} }, $packet;
  93         450  
74             }
75             }
76              
77 57     57 1 2266 sub pieces { @{ $_[0]->{pieces} } }
  57         218  
78              
79             1;
80             __END__
81              
82             =head1 NAME
83              
84             Crypt::OpenPGP::Message - Sequence of PGP packets
85              
86             =head1 SYNOPSIS
87              
88             use Crypt::OpenPGP::Message;
89              
90             my $data; $data .= $_ while <STDIN>;
91             my $msg = Crypt::OpenPGP::Message->new( Data => $data );
92             my @pieces = $msg->pieces;
93              
94             =head1 DESCRIPTION
95              
96             I<Crypt::OpenPGP::Message> provides a container for a sequence of PGP
97             packets. It transparently handles ASCII-armoured messages, as well as
98             cleartext signatures.
99              
100             =head1 USAGE
101              
102             =head2 Crypt::OpenPGP::Message->new( %arg )
103              
104             Constructs a new I<Crypt::OpenPGP::Message> object, presumably to be
105             filled with some data, where the data is a serialized stream of PGP
106             packets.
107              
108             Reads the packets into in-memory packet objects.
109              
110             Returns the new I<Message> object on success, C<undef> on failure.
111              
112             I<%arg> can contain:
113              
114             =over 4
115              
116             =item * Data
117              
118             A scalar string containing the serialized packets.
119              
120             This argument is optional, but either this argument or I<Filename> must
121             be provided.
122              
123             =item * Filename
124              
125             The path to a file that contains a serialized stream of packets.
126              
127             This argument is optional, but either this argument or I<Data> must be
128             provided.
129              
130             =item * IsPacketStream
131              
132             By default I<Crypt::OpenPGP::Message> will attempt to unarmour ASCII-armoured
133             text. Since the armoured text can actually appear anywhere in a string, as
134             long as it starts at the beginning of a line, this can cause problems when a
135             stream of packets happens to include armoured text. At those times you want
136             the packets to be treated as a stream, not as a string that happens to contain
137             armoured text.
138              
139             In this case, set I<IsPacketStream> to a true value, and the ASCII armour
140             detection will be skipped.
141              
142             =back
143              
144             =head2 $msg->pieces
145              
146             Returns an array containing packet objects. For example, if the packet
147             stream contains a public key packet, a user ID packet, and a signature
148             packet, the array will contain three objects: a
149             I<Crypt::OpenPGP::Certificate> object; a I<Crypt::OpenPGP::UserID>
150             object; and a I<Crypt::OpenPGP::Signature> object, in that order.
151              
152             =head1 AUTHOR & COPYRIGHTS
153              
154             Please see the Crypt::OpenPGP manpage for author, copyright, and
155             license information.
156              
157             =cut