File Coverage

blib/lib/Mail/Field.pm
Criterion Covered Total %
statement 18 115 15.6
branch 0 38 0.0
condition 0 18 0.0
subroutine 6 24 25.0
pod 9 10 90.0
total 33 205 16.1


line stmt bran cond sub pod time code
1             # Copyrights 1995-2017 by [Mark Overmeer ].
2             # For other contributors see ChangeLog.
3             # See the manual pages for details on the licensing terms.
4             # Pod stripped from pm file by OODoc 2.02.
5             package Mail::Field;
6 1     1   272 use vars '$VERSION';
  1         2  
  1         41  
7             $VERSION = '2.19';
8              
9              
10 1     1   4 use strict;
  1         2  
  1         16  
11              
12 1     1   4 use Carp;
  1         1  
  1         42  
13 1     1   234 use Mail::Field::Generic;
  1         3  
  1         532  
14              
15              
16             sub _header_pkg_name
17 0     0     { my $header = lc shift;
18 0           $header =~ s/((\b|_)\w)/\U$1/g;
19              
20 0 0         if(length($header) > 8)
21 0           { my @header = split /[-_]+/, $header;
22 0   0       my $chars = int((7 + @header) / @header) || 1;
23 0           $header = substr join('', map {substr $_,0,$chars} @header), 0, 8;
  0            
24             }
25             else
26 0           { $header =~ s/[-_]+//g;
27             }
28              
29 0           'Mail::Field::' . $header;
30             }
31              
32             sub _require_dir
33 0     0     { my($class, $dir, $dir_sep) = @_;
34              
35 0           local *DIR;
36 0 0         opendir DIR, $dir
37             or return;
38              
39 0           my @inc;
40 0           foreach my $f (readdir DIR)
41 0 0         { $f =~ /^([\w\-]+)/ or next;
42 0           my $p = $1;
43 0           my $n = "$dir$dir_sep$p";
44              
45 0 0         if(-d $n )
46 0           { _require_dir("${class}::$f", $n, $dir_sep);
47             }
48             else
49 0           { $p =~ s/-/_/go;
50 0           eval "require ${class}::$p";
51              
52             # added next warning in 2.14, may be ignored for ancient code
53 0 0         warn $@ if $@;
54             }
55             }
56 0           closedir DIR;
57             }
58              
59             sub import
60 0     0     { my $class = shift;
61              
62 0 0         if(@_)
63 0           { local $_;
64             eval "require " . _header_pkg_name($_) || die $@
65 0   0       for @_;
66 0           return;
67             }
68              
69 0           my ($dir, $dir_sep);
70 0           foreach my $f (grep defined $INC{$_}, keys %INC)
71 0 0         { next if $f !~ /^Mail(\W)Field\W/i;
72 0           $dir_sep = $1;
73             # $dir = ($INC{$f} =~ /(.*Mail\W+Field)/i)[0] . $dir_sep;
74 0           ($dir = $INC{$f}) =~ s/(Mail\W+Field).*/$1$dir_sep/;
75 0           last;
76             }
77              
78 0           _require_dir('Mail::Field', $dir, $dir_sep);
79             }
80              
81             # register a header class, this creates a new method in Mail::Field
82             # which will call new on that class
83             sub register
84 0     0 0   { my $thing = shift;
85 0           my $method = lc shift;
86 0   0       my $class = shift || ref($thing) || $thing;
87              
88 0           $method =~ tr/-/_/;
89 0 0         $class = _header_pkg_name $method
90             if $class eq "Mail::Field";
91              
92 0 0         croak "Re-register of $method"
93             if Mail::Field->can($method);
94              
95 1     1   7 no strict 'refs';
  1         2  
  1         354  
96 0           *{$method} = sub {
97 0     0     shift;
98 0 0 0       $class->can('stringify') or eval "require $class" or die $@;
99 0           $class->_build(@_);
100 0           };
101             }
102              
103             # the *real* constructor
104             # if called with one argument then the `parse' method will be called
105             # otherwise the `create' method is called
106              
107             sub _build
108 0     0     { my $self = bless {}, shift;
109 0 0         @_==1 ? $self->parse(@_) : $self->create(@_);
110             }
111              
112             #-------------
113              
114             sub new
115 0     0 1   { my $class = shift;
116 0           my $field = lc shift;
117 0           $field =~ tr/-/_/;
118 0           $class->$field(@_);
119             }
120              
121              
122 0     0 1   sub combine {confess "Combine not implemented" }
123              
124             our $AUTOLOAD;
125             sub AUTOLOAD
126 0     0     { my $method = $AUTOLOAD;
127 0           $method =~ s/.*:://;
128              
129 0 0         $method =~ /^[^A-Z\x00-\x1f\x80-\xff :]+$/
130             or croak "Undefined subroutine &$AUTOLOAD called";
131              
132 0           my $class = _header_pkg_name $method;
133              
134 0 0         unless(eval "require $class")
135 0           { my $tag = $method;
136 0           $tag =~ s/_/-/g;
137             $tag = join '-',
138 0 0         map { /^[b-df-hj-np-tv-z]+$|^MIME$/i ? uc($_) : ucfirst(lc $_) }
  0            
139             split /\-/, $tag;
140              
141 1     1   7 no strict;
  1         1  
  1         544  
142 0           @{"${class}::ISA"} = qw(Mail::Field::Generic);
  0            
143 0     0     *{"${class}::tag"} = sub { $tag };
  0            
  0            
144             }
145              
146 0 0         Mail::Field->can($method)
147             or $class->register($method);
148              
149 0           goto &$AUTOLOAD;
150             }
151              
152              
153             # Of course, the functionality should have been in the Mail::Header class
154             sub extract
155 0     0 1   { my ($class, $tag, $head) = (shift, shift, shift);
156              
157 0           my $method = lc $tag;
158 0           $method =~ tr/-/_/;
159              
160 0 0 0       if(@_==0 && wantarray)
161 0           { my @ret;
162             my $text; # need real copy!
163 0           foreach $text ($head->get($tag))
164 0           { chomp $text;
165 0           push @ret, $class->$method($text);
166             }
167 0           return @ret;
168             }
169              
170 0   0       my $idx = shift || 0;
171 0 0         my $text = $head->get($tag,$idx)
172             or return undef;
173              
174 0           chomp $text;
175 0           $class->$method($text);
176             }
177              
178             #-------------
179              
180             # before 2.00, this method could be called as class method, however
181             # not all extensions supported that.
182             sub create
183 0     0 1   { my ($self, %arg) = @_;
184 0           %$self = ();
185 0           $self->set(\%arg);
186             }
187              
188              
189             # before 2.00, this method could be called as class method, however
190             # not all extensions supported that.
191             sub parse
192 0     0 1   { my $class = ref shift;
193 0           confess "parse() not implemented";
194             }
195              
196             #-------------
197              
198 0     0 1   sub stringify { confess "stringify() not implemented" }
199              
200              
201             sub tag
202 0     0 1   { my $thing = shift;
203 0   0       my $tag = ref($thing) || $thing;
204 0           $tag =~ s/.*:://;
205 0           $tag =~ s/_/-/g;
206              
207             join '-',
208 0 0         map { /^[b-df-hj-np-tv-z]+$|^MIME$/i ? uc($_) : ucfirst(lc $_) }
  0            
209             split /\-/, $tag;
210             }
211              
212              
213 0     0 1   sub set(@) { confess "set() not implemented" }
214              
215             # prevent the calling of AUTOLOAD for DESTROY :-)
216       0     sub DESTROY {}
217              
218             #-------------
219              
220             sub text
221 0     0 1   { my $self = shift;
222 0 0         @_ ? $self->parse(@_) : $self->stringify;
223             }
224              
225             #-------------
226              
227             1;