File Coverage

blib/lib/Courriel/Header/Disposition.pm
Criterion Covered Total %
statement 27 27 100.0
branch n/a
condition n/a
subroutine 9 9 100.0
pod n/a
total 36 36 100.0


line stmt bran cond sub pod time code
1             package Courriel::Header::Disposition;
2              
3 8     8   518 use strict;
  8         11  
  8         235  
4 8     8   32 use warnings;
  8         11  
  8         220  
5 8     8   29 use namespace::autoclean;
  8         13  
  8         58  
6              
7             our $VERSION = '0.42';
8              
9 8     8   594 use Courriel::Types qw( Bool Maybe NonEmptyStr );
  8         11  
  8         59  
10 8     8   48659 use DateTime;
  8         542383  
  8         283  
11 8     8   3399 use DateTime::Format::Mail;
  8         12164  
  8         241  
12 8     8   44 use MooseX::Params::Validate qw( validated_list );
  8         10  
  8         75  
13              
14 8     8   1929 use Moose;
  8         12  
  8         77  
15 8     8   35096 use MooseX::StrictConstructor;
  8         12  
  8         56  
16              
17             extends 'Courriel::Header';
18              
19             with 'Courriel::Role::HeaderWithAttributes' =>
20             { main_value_key => 'disposition' };
21              
22             has '+value' => (
23             required => 0,
24             lazy => 1,
25             builder => 'as_header_value',
26             );
27              
28             has disposition => (
29             is => 'ro',
30             isa => NonEmptyStr,
31             required => 1,
32             );
33              
34             has is_inline => (
35             is => 'ro',
36             isa => Bool,
37             init_arg => undef,
38             lazy => 1,
39             default => sub { $_[0]->disposition() ne 'attachment' },
40             );
41              
42             has is_attachment => (
43             is => 'ro',
44             isa => Bool,
45             init_arg => undef,
46             lazy => 1,
47             default => sub { !$_[0]->is_inline() },
48             );
49              
50             has filename => (
51             is => 'ro',
52             isa => Maybe [NonEmptyStr],
53             init_arg => undef,
54             lazy => 1,
55             default => sub {
56             exists $_[0]->_attributes()->{filename}
57             ? $_[0]->_attributes()->{filename}->value()
58             : undef;
59             },
60             );
61              
62             {
63             my $parser = DateTime::Format::Mail->new( loose => 1 );
64             for my $attr (qw( creation_datetime modification_datetime read_datetime ))
65             {
66             ( my $name_in_header = $attr ) =~ s/_/-/g;
67             $name_in_header =~ s/datetime/date/;
68              
69             my $default = sub {
70             my $attr = $_[0]->_attributes()->{$name_in_header};
71             return unless $attr;
72              
73             my $dt = $parser->parse_datetime( $attr->value() );
74             $dt->set_time_zone('UTC') if $dt;
75              
76             return $dt;
77             };
78              
79             has $attr => (
80             is => 'ro',
81             isa => Maybe ['DateTime'],
82             init_arg => undef,
83             lazy => 1,
84             default => $default,
85             );
86             }
87             }
88              
89             around BUILDARGS => sub {
90             my $orig = shift;
91             my $class = shift;
92              
93             my $p = $class->$orig(@_);
94              
95             $p->{name} = 'Content-Disposition' unless exists $p->{name};
96              
97             return $p;
98             };
99              
100             __PACKAGE__->meta()->make_immutable();
101              
102             1;
103              
104             # ABSTRACT: The content disposition for an email part
105              
106             __END__
107              
108             =pod
109              
110             =encoding utf-8
111              
112             =head1 NAME
113              
114             Courriel::Header::Disposition - The content disposition for an email part
115              
116             =head1 VERSION
117              
118             version 0.42
119              
120             =head1 SYNOPSIS
121              
122             my $disp = $part->content_disposition();
123             print $disp->is_inline();
124             print $disp->is_attachment();
125             print $disp->filename();
126              
127             my %attr = $disp->attributes();
128             while ( my ( $k, $v ) = each %attr ) {
129             print "$k => $v\n";
130             }
131              
132             =head1 DESCRIPTION
133              
134             This class represents the contents of a "Content-Disposition" header attached
135             to an email part. Such headers indicate whether or not a part should be
136             considered an attachment or should be displayed to the user directly. This
137             header may also include information about the attachment's filename, creation
138             date, etc.
139              
140             Here are some typical headers:
141              
142             Content-Disposition: inline
143              
144             Content-Disposition: multipart/alternative; boundary=abcdefghijk
145              
146             Content-Disposition: attachment; filename="Filename.jpg"
147              
148             Content-Disposition: attachment; filename="foo-bar.jpg";
149             creation-date="Tue, 31 May 2011 09:41:13 -0700"
150              
151             =head1 API
152              
153             This class supports the following methods:
154              
155             =head2 Courriel::Header::Disposition->new_from_value( ... )
156              
157             This takes two parameters, C<name> and C<value>. The C<name> is optional, and
158             defaults to "Content-Disposition".
159              
160             The C<value> is parsed and split up into the disposition and attributes.
161              
162             =head2 Courriel::Header::Disposition->new( ... )
163              
164             This method creates a new object. It accepts the following parameters:
165              
166             =over 4
167              
168             =item * name
169              
170             This defaults to 'Content-Type'.
171              
172             =item * value
173              
174             This is the full header value.
175              
176             =item * disposition
177              
178             This should usually either be "inline" or "attachment".
179              
180             In theory, the RFCs allow other values.
181              
182             =item * attributes
183              
184             A hash reference of attributes from the header, such as a filename, creation
185             date, size, etc. The keys are attribute names and the values can either be
186             strings or L<Courriel::HeaderAttribute> objects. Values which are strings will
187             be inflated into objects by the constructor.
188              
189             This is optional, and can be an empty hash reference or omitted entirely.
190              
191             =back
192              
193             =head2 $ct->name()
194              
195             The header name, usually "Content-Disposition".
196              
197             =head2 $ct->value()
198              
199             The raw header value.
200              
201             =head2 $disp->disposition()
202              
203             Returns the disposition value passed to the constructor.
204              
205             =head2 $disp->is_inline()
206              
207             Returns true if the disposition is not equal to "attachment".
208              
209             =head2 $disp->is_attachment()
210              
211             Returns true if the disposition is equal to "attachment".
212              
213             =head2 $disp->filename()
214              
215             Returns the filename found in the attributes, or C<undef>.
216              
217             =head2 $disp->creation_datetime(), $disp->last_modified_datetime(), $disp->read_datetime()
218              
219             These methods look for a corresponding attribute ("creation-date", etc.) and
220             return a L<DateTime> object representing that attribute's value, if it exists.
221              
222             =head2 $disp->attributes()
223              
224             Returns a hash (not a reference) of the attributes passed to the constructor.
225              
226             Attributes are L<Courriel::HeaderAttribute> objects.
227              
228             The keys of the hash are all lower case, though the original casing is
229             preserved in the C<name()> returned by the L<Courriel::HeaderAttribute>
230             object.
231              
232             =head2 $disp->attribute($key)
233              
234             Given a key, returns the named L<Courriel::HeaderAttribute> object. Obviously,
235             this value can be C<undef> if the attribute doesn't exist. Name lookup is
236             case-insensitive.
237              
238             =head2 $disp->attribute_value($key)
239              
240             Given a key, returns the named attribute's value as a string. Obviously, this
241             value can be C<undef> if the attribute doesn't exist. Name lookup is
242             case-insensitive.
243              
244             The attribute is a L<Courriel::HeaderAttribute> object.
245              
246             =head2 $disp->as_header_value()
247              
248             Returns the object as a string suitable for a header value (but not folded).
249              
250             =head1 EXTENDS
251              
252             This class extends L<Courriel::Header>.
253              
254             =head1 ROLES
255              
256             This class does the C<Courriel::Role::HeaderWithAttributes> role.
257              
258             =head1 SUPPORT
259              
260             Bugs may be submitted through L<the RT bug tracker|http://rt.cpan.org/Public/Dist/Display.html?Name=Courriel>
261             (or L<bug-courriel@rt.cpan.org|mailto:bug-courriel@rt.cpan.org>).
262              
263             I am also usually active on IRC as 'drolsky' on C<irc://irc.perl.org>.
264              
265             =head1 AUTHOR
266              
267             Dave Rolsky <autarch@urth.org>
268              
269             =head1 COPYRIGHT AND LICENCE
270              
271             This software is Copyright (c) 2016 by Dave Rolsky.
272              
273             This is free software, licensed under:
274              
275             The Artistic License 2.0 (GPL Compatible)
276              
277             =cut