File Coverage

lib/MIME/Types.pm
Criterion Covered Total %
statement 138 151 91.3
branch 60 82 73.1
condition 8 15 53.3
subroutine 22 28 78.5
pod 13 15 86.6
total 241 291 82.8


line stmt bran cond sub pod time code
1             # Copyrights 1999-2021 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             # This code is part of distribution MIME::Types. Meta-POD processed with
6             # OODoc into POD and HTML manual-pages. See README.md
7             # Copyright Mark Overmeer. Licensed under the same terms as Perl itself.
8              
9             package MIME::Types;
10 4     4   275207 use vars '$VERSION';
  4         40  
  4         276  
11             $VERSION = '2.22';
12              
13              
14 4     4   23 use strict;
  4         8  
  4         76  
15              
16 4     4   1509 use MIME::Type ();
  4         10  
  4         85  
17 4     4   26 use File::Spec ();
  4         6  
  4         73  
18 4     4   18 use File::Basename qw(dirname);
  4         5  
  4         394  
19 4     4   27 use List::Util qw(first);
  4         7  
  4         7690  
20              
21              
22             my %typedb;
23 4     4 1 259 sub new(@) { (bless {}, shift)->init( {@_} ) }
24              
25             sub init($)
26 4     4 0 13 { my ($self, $args) = @_;
27 4 50       27 keys %typedb or $self->_read_db($args);
28 4         35 $self;
29             }
30              
31             sub _read_db($)
32 4     4   8 { my ($self, $args) = @_;
33 4         8 my $skip_extensions = $args->{skip_extensions};
34 4         8 my $only_complete = $args->{only_complete};
35 4         6 my $only_iana = $args->{only_iana};
36              
37             my $db = $ENV{PERL_MIME_TYPE_DB}
38             || $args->{db_file}
39 4   33     360 || File::Spec->catfile(dirname(__FILE__), 'types.db');
40              
41 4         20 local *DB;
42 4 50   4   21 open DB, '<:encoding(utf8)', $db
  4         7  
  4         24  
  4         108  
43             or die "cannot open type database in $db: $!\n";
44              
45 4         48298 while(1)
46 192         482 { my $header = ;
47 192 100       372 defined $header or last;
48 188         230 chomp $header;
49              
50             # This logic is entangled with the bin/collect_types script
51 188         729 my ($count, $major, $is_iana, $has_ext) = split /\:/, $header;
52 188 100 33     806 my $skip_section = $major eq 'EXTENSIONS' ? $skip_extensions
53             : (($only_iana && !$is_iana) || ($only_complete && !$has_ext));
54              
55             #warn "Skipping section $header\n" if $skip_section;
56 188         390 (my $section = $major) =~ s/^x-//;
57 188 100       280 if($major eq 'EXTENSIONS')
58 4         8 { local $_;
59 4         21 while()
60 8924 100       19952 { last if m/^$/;
61 8920 50       11415 next if $skip_section;
62 8920         9709 chomp;
63 8920 50       55934 $typedb{$section}{$1} = $2 if m/(.*);(.*)/;
64             }
65             }
66             else
67 184         201 { local $_;
68 184         461 while()
69 12168 100       27190 { last if m/^$/;
70 11984 50       15291 next if $skip_section;
71 11984         13571 chomp;
72 11984 50       79454 $typedb{$section}{$1} = "$major/$_" if m/^(?:x-)?([^;]+)/;
73             }
74             }
75             }
76              
77 4         109 close DB;
78             }
79              
80             # Catalyst-Plugin-Static-Simple uses it :(
81       0 0   sub create_type_index {}
82              
83             #-------------------------------------------
84              
85             sub type($)
86 4069     4069 1 10685 { my $spec = lc $_[1];
87 4069 50       6911 $spec = 'text/plain' if $spec eq 'text'; # old mailers
88              
89 4069 50       14194 $spec =~ m!^(?:x\-)?([^/]+)/(?:x-)?(.*)!
90             or return;
91              
92 4069 50       10230 my $section = $typedb{$1} or return;
93 4069 50       10664 my $record = $section->{$2} or return;
94 4069 100       9018 return $record if ref $record; # already extended
95              
96 2034         2904 my $simple = $2;
97 2034         6253 my ($type, $ext, $enc) = split m/\;/, $record;
98 2034         2995 my $os = undef; # XXX TODO
99              
100 2034         6631 $section->{$simple} = MIME::Type->new
101             ( type => $type
102             , extensions => [split /\,/, $ext]
103             , encoding => $enc
104             , system => $os
105             );
106             }
107              
108              
109             sub mimeTypeOf($)
110 25     25 1 901 { my ($self, $name) = @_;
111 25         136 (my $ext = lc $name) =~ s/.*\.//;
112 25 100       109 my $type = $typedb{EXTENSIONS}{$ext} or return;
113 23         52 $self->type($type);
114             }
115              
116              
117             sub addType(@)
118 3     3 1 43 { my $self = shift;
119              
120 3         8 foreach my $type (@_)
121 3         7 { my ($major, $minor) = split m!/!, $type->simplified;
122 3         10 $typedb{$major}{$minor} = $type;
123 3         7 $typedb{EXTENSIONS}{$_} = $type for $type->extensions;
124             }
125 3         6 $self;
126             }
127              
128              
129             sub types()
130 0     0 1 0 { my $self = shift;
131 0         0 my @types;
132 0         0 foreach my $section (keys %typedb)
133 0 0       0 { next if $section eq 'EXTENSIONS';
134             push @types, map $_->type("$section/$_"),
135 0         0 sort keys %{$typedb{$section}};
  0         0  
136             }
137 0         0 @types;
138             }
139              
140              
141             sub listTypes()
142 6     6 1 12 { my $self = shift;
143 6         12 my @types;
144 6         74 foreach my $section (keys %typedb)
145 138 100       306 { next if $section eq 'EXTENSIONS';
146 132         169 foreach my $sub (sort keys %{$typedb{$section}})
  132         14279  
147 17814         36291 { my $record = $typedb{$section}{$sub};
148 17814 50       51702 push @types, ref $record ? $record->type
    100          
149             : $record =~ m/^([^;]+)/ ? $1 : die;
150             }
151             }
152 6         23646 @types;
153             }
154              
155              
156 0     0 1 0 sub extensions { keys %{$typedb{EXTENSIONS}} }
  0         0  
157 0     0   0 sub _MojoExtTable() {$typedb{EXTENSIONS}}
158              
159             #-------------
160              
161             sub httpAccept($)
162 7     7 1 3782 { my $self = shift;
163 7         10 my @listed;
164              
165 7         40 foreach (split /\,\s*/, shift)
166             {
167 17 50       83 m!^ ([a-zA-Z0-9-]+ | \*) / ( [a-zA-Z0-9+-]+ | \* )
168             \s* (?: \;\s*q\=\s* ([0-9]+(?:\.[0-9]*)?) \s* )?
169             (\;.* | )
170             $ !x or next;
171              
172 17         54 my $mime = "$1/$2$4";
173 17 100       37 my $q = defined $3 ? $3 : 1; # q, default=1
174              
175             # most complex first
176 17 100       52 $q += $4 ? +0.01 : $1 eq '*' ? -0.02 : $2 eq '*' ? -0.01 : 0;
    100          
    50          
177              
178             # keep order
179 17         35 $q -= @listed*0.0001;
180              
181 17         44 push @listed, [ $mime => $q ];
182             }
183 7         33 map $_->[0], sort {$b->[1] <=> $a->[1]} @listed;
  15         55  
184             }
185              
186              
187             sub httpAcceptBest($@)
188 8     8 1 1262 { my $self = shift;
189 8 100       25 my @accept = ref $_[0] eq 'ARRAY' ? @{(shift)} : $self->httpAccept(shift);
  4         9  
190 8         10 my $match;
191              
192 8         14 foreach my $acc (@accept)
193 10         18 { $acc =~ s/\s*\;.*//; # remove attributes
194 17     17   43 my $m = $acc !~ s#/\*$## ? first { $_->equals($acc) } @_
195             : $acc eq '*' ? $_[0] # $acc eq */*
196 10 0   0   57 : first { $_->mediaType eq $acc } @_;
  0 50       0  
197 10 100       51 return $m if defined $m;
198             }
199              
200 1         2 ();
201             }
202              
203              
204             sub httpAcceptSelect($@)
205 4     4 1 10 { my ($self, $accept) = (shift, shift);
206 4 50       15 my $fns = !@_ ? return () : ref $_[0] eq 'ARRAY' ? shift : [@_];
    50          
207              
208 4 100       12 unless(defined $accept)
209 1         2 { my $fn = $fns->[0];
210 1         3 return ($fn, $self->mimeTypeOf($fn));
211             }
212              
213             # create mapping type -> filename
214 3         5 my (%have, @have);
215 3         6 foreach my $fn (@$fns)
216 6 50       11 { my $type = $self->mimeTypeOf($fn) or next;
217 6         14 $have{$type->simplified} = $fn;
218 6         14 push @have, $type;
219             }
220              
221 3         13 my $type = $self->httpAcceptBest($accept, @have);
222 3 100       11 defined $type ? ($have{$type}, $type) : ();
223             }
224              
225             #-------------------------------------------
226             # OLD INTERFACE (version 0.06 and lower)
227              
228              
229 4     4   31 use base 'Exporter';
  4         31  
  4         1835  
230             our @EXPORT_OK = qw(by_suffix by_mediatype import_mime_types);
231              
232              
233             my $mime_types;
234              
235             sub by_suffix($)
236 7     7 1 6442 { my $filename = shift;
237 7   66     33 $mime_types ||= MIME::Types->new;
238 7         25 my $mime = $mime_types->mimeTypeOf($filename);
239              
240 7 100       29 my @data = defined $mime ? ($mime->type, $mime->encoding) : ('','');
241 7 100       43 wantarray ? @data : \@data;
242             }
243              
244              
245             sub by_mediatype($)
246 8     8 1 15223 { my $type = shift;
247 8   33     29 $mime_types ||= MIME::Types->new;
248              
249 8         15 my @found;
250 8 100 100     59 if(!ref $type && index($type, '/') >= 0)
251 2         7 { my $mime = $mime_types->type($type);
252 2 50       6 @found = $mime if $mime;
253             }
254             else
255 6 100       112 { my $search = ref $type eq 'Regexp' ? $type : qr/$type/i;
256 6         27 @found = map $mime_types->type($_),
257             grep $_ =~ $search,
258             $mime_types->listTypes;
259             }
260              
261 8         1231 my @data;
262 8         37 foreach my $mime (@found)
263 4038         7133 { push @data, map [$_, $mime->type, $mime->encoding],
264             $mime->extensions;
265             }
266              
267 8 100       1748 wantarray ? @data : \@data;
268             }
269              
270              
271             sub import_mime_types($)
272 0     0 1   { my $filename = shift;
273 4     4   29 use Carp;
  4         7  
  4         365  
274 0           croak <<'CROAK';
275             import_mime_types is not supported anymore: if you have types to add
276             please send them to the author.
277             CROAK
278             }
279              
280             1;