File Coverage

blib/lib/Email/Simple/Header.pm
Criterion Covered Total %
statement 117 121 96.6
branch 47 58 81.0
condition 12 21 57.1
subroutine 19 19 100.0
pod 10 10 100.0
total 205 229 89.5


line stmt bran cond sub pod time code
1 20     20   48234 use strict;
  20         36  
  20         395  
2 20     20   70 use warnings;
  20         29  
  20         609  
3             package Email::Simple::Header;
4             # ABSTRACT: the header of an Email::Simple message
5             $Email::Simple::Header::VERSION = '2.216';
6 20     20   86 use Carp ();
  20         27  
  20         27831  
7              
8             require Email::Simple;
9              
10             #pod =head1 SYNOPSIS
11             #pod
12             #pod my $email = Email::Simple->new($text);
13             #pod
14             #pod my $header = $email->header_obj;
15             #pod print $header->as_string;
16             #pod
17             #pod =head1 DESCRIPTION
18             #pod
19             #pod This method implements the headers of an Email::Simple object. It is a very
20             #pod minimal interface, and is mostly for private consumption at the moment.
21             #pod
22             #pod =method new
23             #pod
24             #pod my $header = Email::Simple::Header->new($head, \%arg);
25             #pod
26             #pod C<$head> is a string containing a valid email header, or a reference to such a
27             #pod string. If a reference is passed in, don't expect that it won't be altered.
28             #pod
29             #pod Valid arguments are:
30             #pod
31             #pod crlf - the header's newline; defaults to CRLF
32             #pod
33             #pod =cut
34              
35             # We need to be able to:
36             # * get all values by lc name
37             # * produce all pairs, with case intact
38              
39             sub new {
40 50     50 1 1292 my ($class, $head, $arg) = @_;
41              
42 50 100       111 my $head_ref = ref $head ? $head : \$head;
43              
44 50   100     142 my $self = { mycrlf => $arg->{crlf} || "\x0d\x0a", };
45              
46 50         105 my $headers = $class->_header_to_list($head_ref, $self->{mycrlf});
47              
48             # for my $header (@$headers) {
49             # push @{ $self->{order} }, $header->[0];
50             # push @{ $self->{head}{ $header->[0] } }, $header->[1];
51             # }
52             #
53             # $self->{header_names} = { map { lc $_ => $_ } keys %{ $self->{head} } };
54 50         86 $self->{headers} = $headers;
55              
56 50         181 bless $self => $class;
57             }
58              
59             sub _header_to_list {
60 50     50   92 my ($self, $head, $mycrlf) = @_;
61              
62 50         63 my @headers;
63              
64 50         104 my $crlf = Email::Simple->__crlf_re;
65              
66 50         558 while ($$head =~ m/\G(.+?)$crlf/go) {
67 422         723 local $_ = $1;
68              
69 422 100 100     1422 if (/^\s+/ or not /^([^:]+):\s*(.*)/) {
70             # This is a continuation line. We fold it onto the end of
71             # the previous header.
72 47 100       88 next if !@headers; # Well, that sucks. We're continuing nothing?
73              
74 46         105 (my $trimmed = $_) =~ s/^\s+//;
75 46 100       134 $headers[-1][0] .= $headers[-1][0] =~ /\S/ ? " $trimmed" : $trimmed;
76 46         184 $headers[-1][1] .= "$mycrlf$_";
77             } else {
78 375         1656 push @headers, $1, [ $2, $_ ];
79             }
80             }
81              
82 50         136 return \@headers;
83             }
84              
85             #pod =method as_string
86             #pod
87             #pod my $string = $header->as_string(\%arg);
88             #pod
89             #pod This returns a stringified version of the header.
90             #pod
91             #pod =cut
92              
93             # RFC 2822, 3.6:
94             # ...for the purposes of this standard, header fields SHOULD NOT be reordered
95             # when a message is transported or transformed. More importantly, the trace
96             # header fields and resent header fields MUST NOT be reordered, and SHOULD be
97             # kept in blocks prepended to the message.
98              
99             sub as_string {
100 49     49 1 76 my ($self, $arg) = @_;
101 49   50     195 $arg ||= {};
102              
103 49         62 my $header_str = '';
104              
105 49         66 my $headers = $self->{headers};
106              
107 49         81 my $fold_arg = {
108             # at => (exists $arg->{fold_at} ? $arg->{fold_at} : $self->default_fold_at),
109             # indent => (exists $arg->{fold_indent} ? $arg->{fold_indent} : $self->default_fold_indent),
110             at => $self->_default_fold_at,
111             indent => $self->_default_fold_indent,
112             };
113              
114 49         113 for (my $i = 0; $i < @$headers; $i += 2) {
115 441 100       616 if (ref $headers->[ $i + 1 ]) {
116 393         507 $header_str .= $headers->[ $i + 1 ][1] . $self->crlf;
117             } else {
118 48         79 my $header = "$headers->[$i]: $headers->[$i + 1]";
119              
120 48         77 $header_str .= $self->_fold($header, $fold_arg);
121             }
122             }
123              
124 49         149 return $header_str;
125             }
126              
127             #pod =method header_names
128             #pod
129             #pod This method returns a list of the unique header names found in this header, in
130             #pod no particular order.
131             #pod
132             #pod =cut
133              
134             sub header_names {
135 6     6 1 8 my $headers = $_[0]->{headers};
136              
137 6         7 my %seen;
138 14         44 grep { !$seen{ lc $_ }++ }
139 6         22 map { $headers->[ $_ * 2 ] } 0 .. @$headers / 2 - 1;
  14         20  
140             }
141              
142             #pod =method header_raw_pairs
143             #pod
144             #pod my @pairs = $header->header_raw_pairs;
145             #pod my $first_name = $pairs[0];
146             #pod my $first_value = $pairs[1];
147             #pod
148             #pod This method returns a list of all the field/value pairs in the header, in the
149             #pod order that they appear in the header. (Remember: don't try assigning that to a
150             #pod hash. Some fields may appear more than once!)
151             #pod
152             #pod =method header_pairs
153             #pod
154             #pod L is another name for L, which was the original
155             #pod name for the method and which you'll see most often. In general, though, it's
156             #pod better to be explicit and use L. (In Email::MIME,
157             #pod L exists for letting the library do the header decoding for
158             #pod you.)
159             #pod
160             #pod =cut
161              
162             sub header_raw_pairs {
163 12     12 1 14 my ($self) = @_;
164              
165 12         13 my @pairs = map {; _str_value($_) } @{ $self->{headers} };
  92         139  
  12         19  
166              
167 12         84 return @pairs;
168             }
169              
170             sub header_pairs {
171 12     12 1 19 my ($self) = @_;
172 12         19 $self->header_raw_pairs;
173             }
174              
175             #pod =method header_raw
176             #pod
177             #pod my $first_value = $header->header_raw($field);
178             #pod my $nth_value = $header->header_raw($field, $index);
179             #pod my @all_values = $header->header_raw($field);
180             #pod
181             #pod This method returns the value or values of the given header field. If the
182             #pod named field does not appear in the header, this method returns false.
183             #pod
184             #pod =method header
185             #pod
186             #pod This method just calls C. It's the older name for C,
187             #pod but it can be a problem because L, a subclass of Email::Simple,
188             #pod makes C
return the header's decoded value.
189             #pod
190             #pod =cut
191              
192 163 100   163   462 sub _str_value { return ref $_[0] ? $_[0][0] : $_[0] }
193              
194             sub header_raw {
195 74     74 1 5501 my ($self, $field, $index) = @_;
196              
197 74         100 my $headers = $self->{headers};
198 74         108 my $lc_field = lc $field;
199              
200 74 100 66     218 if (wantarray and not defined $index) {
201 22         34 return map { _str_value($headers->[ $_ * 2 + 1 ]) }
202 10         35 grep { lc $headers->[ $_ * 2 ] eq $lc_field } 0 .. @$headers / 2 - 1;
  53         82  
203             } else {
204 64 100       120 $index = 0 unless defined $index;
205 64         138 my $max = @$headers / 2 - 1;
206 64 100       203 my @indexes = $index >= 0 ? (0 .. $max) : reverse(0 .. $max);
207 64 100       118 $index = -1-$index if $index < 0;
208 64         95 for (@indexes) {
209 249 100       402 next unless lc $headers->[ $_ * 2 ] eq $lc_field;
210 93 100       179 return _str_value($headers->[ $_ * 2 + 1 ]) if $index-- == 0;
211             }
212 15         67 return undef;
213             }
214             }
215              
216             *header = \&header_raw;
217              
218             #pod =method header_raw_set
219             #pod
220             #pod $header->header_raw_set($field => @values);
221             #pod
222             #pod This method updates the value of the given header. Existing headers have their
223             #pod values set in place. Additional headers are added at the end. If no values
224             #pod are given to set, the header will be removed from to the message entirely.
225             #pod
226             #pod =method header_set
227             #pod
228             #pod L is another name for L, which was the original
229             #pod name for the method and which you'll see most often. In general, though, it's
230             #pod better to be explicit and use L. (In Email::MIME,
231             #pod L exists for letting the library do the header encoding for
232             #pod you.)
233             #pod
234             #pod =cut
235              
236             # Header fields are lines composed of a field name, followed by a colon (":"),
237             # followed by a field body, and terminated by CRLF. A field name MUST be
238             # composed of printable US-ASCII characters (i.e., characters that have values
239             # between 33 and 126, inclusive), except colon. A field body may be composed
240             # of any US-ASCII characters, except for CR and LF.
241              
242             # However, a field body may contain CRLF when used in header "folding" and
243             # "unfolding" as described in section 2.2.3.
244              
245             sub header_raw_set {
246 21     21 1 33 my ($self, $field, @data) = @_;
247              
248             # I hate this block. -- rjbs, 2006-10-06
249 21 50       45 if ($Email::Simple::GROUCHY) {
250 0 0       0 Carp::croak "field name contains illegal characters"
251             unless $field =~ /^[\x21-\x39\x3b-\x7e]+$/;
252 0 0       0 Carp::carp "field name is not limited to hyphens and alphanumerics"
253             unless $field =~ /^[\w-]+$/;
254             }
255              
256 21         31 my $headers = $self->{headers};
257              
258 21         35 my $lc_field = lc $field;
259 143         190 my @indices = grep { lc $headers->[$_] eq $lc_field }
260 21         58 map { $_ * 2 } 0 .. @$headers / 2 - 1;
  143         167  
261              
262 21 100       68 if (@indices > @data) {
    100          
263 2         3 my $overage = @indices - @data;
264 2         5 splice @{$headers}, $_, 2 for reverse @indices[ -$overage .. -1 ];
  3         6  
265 2         4 pop @indices for (1 .. $overage);
266             } elsif (@data > @indices) {
267 11         16 my $underage = @data - @indices;
268 11         22 for (1 .. $underage) {
269 11         20 push @$headers, $field, undef; # temporary value
270 11         21 push @indices, $#$headers - 1;
271             }
272             }
273              
274 21         49 for (0 .. $#indices) {
275 23         47 $headers->[ $indices[$_] + 1 ] = $data[$_];
276             }
277              
278 21 100       82 return wantarray ? @data : $data[0];
279             }
280              
281             sub header_set {
282 15     15 1 31 my ($self, $field, @data) = @_;
283 15         32 $self->header_raw_set($field, @data);
284             }
285              
286             #pod =method header_raw_prepend
287             #pod
288             #pod $header->header_raw_prepend($field => $value);
289             #pod
290             #pod This method adds a new instance of the name field as the first field in the
291             #pod header.
292             #pod
293             #pod =cut
294              
295             sub header_raw_prepend {
296 9     9 1 16 my ($self, $field, $value) = @_;
297              
298 9 50       39 Carp::confess("tried to prepend raw header with undefined field name")
299             unless defined $field;
300              
301 9 50       13 Carp::confess(qq{tried to prepend raw header "$field" with undefined value})
302             unless defined $value;
303              
304 9         7 unshift @{ $self->{headers} }, $field => $value;
  9         19  
305              
306 9         14 return;
307             }
308              
309             #pod =method crlf
310             #pod
311             #pod This method returns the newline string used in the header.
312             #pod
313             #pod =cut
314              
315 436     436 1 929 sub crlf { $_[0]->{mycrlf} }
316              
317             # =method fold
318             #
319             # my $folded = $header->fold($line, \%arg);
320             #
321             # Given a header string, this method returns a folded version, if the string is
322             # long enough to warrant folding. This method is used internally.
323             #
324             # Valid arguments are:
325             #
326             # at - fold lines to be no longer than this length, if possible
327             # if given and false, never fold headers
328             # indent - indent lines with this string
329              
330             # =cut
331              
332             sub _fold {
333 48     48   63 my ($self, $line, $arg) = @_;
334 48   50     65 $arg ||= {};
335              
336 48 50       69 $arg->{at} = $self->_default_fold_at unless exists $arg->{at};
337              
338 48 50       59 $arg->{indent} = $self->_default_fold_indent unless exists $arg->{indent};
339              
340 48   33     62 my $indent = $arg->{indent} || $self->_default_fold_indent;
341              
342             # We will not folder headers if...
343             # * the header has vertical whitespace
344             # * all vertical whitespace is followed by horizontal whitespace or END
345 48 100       101 if ($line =~ /\n/) {
346 21 100       40 if ($line =~ s/\n([^\s\t])/\n$indent$1/g) {
347 1         173 Carp::carp("bad space in header: newline followed by non-space: $line");
348             } else {
349 20 100       42 $line .= $self->crlf unless $line =~ /\n$/;
350 20         48 return $line;
351             }
352             }
353              
354 28 50 33     126 return $line . $self->crlf unless $arg->{at} and $arg->{at} > 0;
355              
356 28   33     74 my $limit = ($arg->{at} || $self->_default_fold_at) - 1;
357              
358 28 100       62 return $line . $self->crlf if length $line <= $limit;
359              
360 1         3 return $self->__fold_objless($line, $limit, $indent, $self->crlf);
361              
362             }
363              
364             sub __fold_objless {
365 22     22   35 my ($self, $line, $limit, $indent, $crlf) = @_;
366              
367             # We know it will not contain any new lines at present
368 22         25 my $folded = "";
369 22         28 while (length $line) {
370 25 50       140 if ($line =~ s/^(.{0,$limit})(\s|\z)//) {
371 25         53 $folded .= $1 . $crlf;
372 25 100       57 $folded .= $indent if length $line;
373             } else {
374             # Basically nothing we can do. :(
375 0         0 $folded .= $line . $crlf;
376 0         0 last;
377             }
378             }
379              
380 22         68 return $folded;
381             }
382              
383             # =method default_fold_at
384             #
385             # This method (provided for subclassing) returns the default length at which to
386             # try to fold header lines. The default default is 78.
387             #
388             # =cut
389              
390 49     49   74 sub _default_fold_at { 78 }
391              
392             # =method default_fold_indent
393             #
394             # This method (provided for subclassing) returns the default string used to
395             # indent folded headers. The default default is a single space.
396             #
397             # =cut
398              
399 49     49   107 sub _default_fold_indent { " " }
400              
401             1;
402              
403             __END__