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-2022 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.03.
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   281935 use vars '$VERSION';
  4         47  
  4         244  
11             $VERSION = '2.23';
12              
13              
14 4     4   23 use strict;
  4         6  
  4         75  
15              
16 4     4   1489 use MIME::Type ();
  4         11  
  4         83  
17 4     4   26 use File::Spec ();
  4         5  
  4         73  
18 4     4   19 use File::Basename qw(dirname);
  4         8  
  4         428  
19 4     4   29 use List::Util qw(first);
  4         6  
  4         7457  
20              
21              
22             my %typedb;
23 4     4 1 262 sub new(@) { (bless {}, shift)->init( {@_} ) }
24              
25             sub init($)
26 4     4 0 12 { my ($self, $args) = @_;
27 4 50       28 keys %typedb or $self->_read_db($args);
28 4         35 $self;
29             }
30              
31             sub _read_db($)
32 4     4   12 { my ($self, $args) = @_;
33 4         10 my $skip_extensions = $args->{skip_extensions};
34 4         8 my $only_complete = $args->{only_complete};
35 4         9 my $only_iana = $args->{only_iana};
36              
37             my $db = $ENV{PERL_MIME_TYPE_DB}
38             || $args->{db_file}
39 4   33     359 || File::Spec->catfile(dirname(__FILE__), 'types.db');
40              
41 4         20 local *DB;
42 4 50   4   24 open DB, '<:encoding(utf8)', $db
  4         7  
  4         21  
  4         112  
43             or die "cannot open type database in $db: $!\n";
44              
45 4         47862 while(1)
46 192         517 { my $header = ;
47 192 100       383 defined $header or last;
48 188         250 chomp $header;
49              
50             # This logic is entangled with the bin/collect_types script
51 188         757 my ($count, $major, $is_iana, $has_ext) = split /\:/, $header;
52 188 100 33     929 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         431 (my $section = $major) =~ s/^x-//;
57 188 100       316 if($major eq 'EXTENSIONS')
58 4         7 { local $_;
59 4         19 while()
60 9016 100       20512 { last if m/^$/;
61 9012 50       11384 next if $skip_section;
62 9012         9617 chomp;
63 9012 50       59245 $typedb{$section}{$1} = $2 if m/(.*);(.*)/;
64             }
65             }
66             else
67 184         204 { local $_;
68 184         454 while()
69 12456 100       28603 { last if m/^$/;
70 12272 50       15528 next if $skip_section;
71 12272         13204 chomp;
72 12272 50       81460 $typedb{$section}{$1} = "$major/$_" if m/^(?:x-)?([^;]+)/;
73             }
74             }
75             }
76              
77 4         128 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 4157     4157 1 10796 { my $spec = lc $_[1];
87 4157 50       6969 $spec = 'text/plain' if $spec eq 'text'; # old mailers
88              
89 4157 50       15338 $spec =~ m!^(?:x\-)?([^/]+)/(?:x-)?(.*)!
90             or return;
91              
92 4157 50       10644 my $section = $typedb{$1} or return;
93 4157 50       10963 my $record = $section->{$2} or return;
94 4157 100       8957 return $record if ref $record; # already extended
95              
96 2078         3026 my $simple = $2;
97 2078         6323 my ($type, $ext, $enc) = split m/\;/, $record;
98 2078         3169 my $os = undef; # XXX TODO
99              
100 2078         6618 $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 863 { my ($self, $name) = @_;
111 25         127 (my $ext = lc $name) =~ s/.*\.//;
112 25 100       89 my $type = $typedb{EXTENSIONS}{$ext} or return;
113 23         58 $self->type($type);
114             }
115              
116              
117             sub addType(@)
118 3     3 1 61 { my $self = shift;
119              
120 3         7 foreach my $type (@_)
121 3         5 { my ($major, $minor) = split m!/!, $type->simplified;
122 3         9 $typedb{$major}{$minor} = $type;
123 3         5 $typedb{EXTENSIONS}{$_} = $type for $type->extensions;
124             }
125 3         11 $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 13 { my $self = shift;
143 6         11 my @types;
144 6         56 foreach my $section (keys %typedb)
145 138 100       276 { next if $section eq 'EXTENSIONS';
146 132         162 foreach my $sub (sort keys %{$typedb{$section}})
  132         13908  
147 18246         34337 { my $record = $typedb{$section}{$sub};
148 18246 50       50874 push @types, ref $record ? $record->type
    100          
149             : $record =~ m/^([^;]+)/ ? $1 : die;
150             }
151             }
152 6         21809 @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 3732 { my $self = shift;
163 7         12 my @listed;
164              
165 7         40 foreach (split /\,\s*/, shift)
166             {
167 17 50       89 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         52 my $mime = "$1/$2$4";
173 17 100       35 my $q = defined $3 ? $3 : 1; # q, default=1
174              
175             # most complex first
176 17 100       59 $q += $4 ? +0.01 : $1 eq '*' ? -0.02 : $2 eq '*' ? -0.01 : 0;
    100          
    50          
177              
178             # keep order
179 17         31 $q -= @listed*0.0001;
180              
181 17         55 push @listed, [ $mime => $q ];
182             }
183 7         36 map $_->[0], sort {$b->[1] <=> $a->[1]} @listed;
  15         60  
184             }
185              
186              
187             sub httpAcceptBest($@)
188 8     8 1 1244 { my $self = shift;
189 8 100       26 my @accept = ref $_[0] eq 'ARRAY' ? @{(shift)} : $self->httpAccept(shift);
  4         9  
190 8         9 my $match;
191              
192 8         14 foreach my $acc (@accept)
193 10         17 { $acc =~ s/\s*\;.*//; # remove attributes
194 17     17   38 my $m = $acc !~ s#/\*$## ? first { $_->equals($acc) } @_
195             : $acc eq '*' ? $_[0] # $acc eq */*
196 10 0   0   58 : first { $_->mediaType eq $acc } @_;
  0 50       0  
197 10 100       52 return $m if defined $m;
198             }
199              
200 1         3 ();
201             }
202              
203              
204             sub httpAcceptSelect($@)
205 4     4 1 10 { my ($self, $accept) = (shift, shift);
206 4 50       17 my $fns = !@_ ? return () : ref $_[0] eq 'ARRAY' ? shift : [@_];
    50          
207              
208 4 100       11 unless(defined $accept)
209 1         3 { my $fn = $fns->[0];
210 1         3 return ($fn, $self->mimeTypeOf($fn));
211             }
212              
213             # create mapping type -> filename
214 3         4 my (%have, @have);
215 3         7 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         12 my $type = $self->httpAcceptBest($accept, @have);
222 3 100       13 defined $type ? ($have{$type}, $type) : ();
223             }
224              
225             #-------------------------------------------
226             # OLD INTERFACE (version 0.06 and lower)
227              
228              
229 4     4   43 use base 'Exporter';
  4         18  
  4         1949  
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 6063 { my $filename = shift;
237 7   66     28 $mime_types ||= MIME::Types->new;
238 7         22 my $mime = $mime_types->mimeTypeOf($filename);
239              
240 7 100       27 my @data = defined $mime ? ($mime->type, $mime->encoding) : ('','');
241 7 100       28 wantarray ? @data : \@data;
242             }
243              
244              
245             sub by_mediatype($)
246 8     8 1 14435 { my $type = shift;
247 8   33     27 $mime_types ||= MIME::Types->new;
248              
249 8         14 my @found;
250 8 100 100     55 if(!ref $type && index($type, '/') >= 0)
251 2         6 { my $mime = $mime_types->type($type);
252 2 50       7 @found = $mime if $mime;
253             }
254             else
255 6 100       111 { my $search = ref $type eq 'Regexp' ? $type : qr/$type/i;
256 6         25 @found = map $mime_types->type($_),
257             grep $_ =~ $search,
258             $mime_types->listTypes;
259             }
260              
261 8         930 my @data;
262 8         25 foreach my $mime (@found)
263 4126         7078 { push @data, map [$_, $mime->type, $mime->encoding],
264             $mime->extensions;
265             }
266              
267 8 100       1126 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         410  
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;