File Coverage

blib/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   275847 use vars '$VERSION';
  4         43  
  4         255  
11             $VERSION = '2.24';
12              
13              
14 4     4   25 use strict;
  4         23  
  4         83  
15              
16 4     4   1497 use MIME::Type ();
  4         17  
  4         88  
17 4     4   26 use File::Spec ();
  4         6  
  4         77  
18 4     4   20 use File::Basename qw(dirname);
  4         7  
  4         1880  
19 4     4   31 use List::Util qw(first);
  4         6  
  4         7185  
20              
21              
22             my %typedb;
23 4     4 1 270 sub new(@) { (bless {}, shift)->init( {@_} ) }
24              
25             sub init($)
26 4     4 0 14 { my ($self, $args) = @_;
27 4 50       27 keys %typedb or $self->_read_db($args);
28 4         39 $self;
29             }
30              
31             sub _read_db($)
32 4     4   11 { my ($self, $args) = @_;
33 4         10 my $skip_extensions = $args->{skip_extensions};
34 4         8 my $only_complete = $args->{only_complete};
35 4         8 my $only_iana = $args->{only_iana};
36              
37             my $db = $ENV{PERL_MIME_TYPE_DB}
38             || $args->{db_file}
39 4   33     378 || File::Spec->catfile(dirname(__FILE__), 'types.db');
40              
41 4         22 local *DB;
42 4 50   4   28 open DB, '<:encoding(utf8)', $db
  4         7  
  4         27  
  4         108  
43             or die "cannot open type database in $db: $!\n";
44              
45 4         48609 while(1)
46 192         454 { my $header = ;
47 192 100       381 defined $header or last;
48 188         243 chomp $header;
49              
50             # This logic is entangled with the bin/collect_types script
51 188         745 my ($count, $major, $is_iana, $has_ext) = split /\:/, $header;
52 188 100 33     844 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         425 (my $section = $major) =~ s/^x-//;
57 188 100       300 if($major eq 'EXTENSIONS')
58 4         14 { local $_;
59 4         22 while()
60 9016 100       20700 { last if m/^$/;
61 9012 50       11936 next if $skip_section;
62 9012         10171 chomp;
63 9012 50       58020 $typedb{$section}{$1} = $2 if m/(.*);(.*)/;
64             }
65             }
66             else
67 184         233 { local $_;
68 184         419 while()
69 12456 100       28439 { last if m/^$/;
70 12272 50       16285 next if $skip_section;
71 12272         14139 chomp;
72 12272 50       81796 $typedb{$section}{$1} = "$major/$_" if m/^(?:x-)?([^;]+)/;
73             }
74             }
75             }
76              
77 4         105 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 4159     4159 1 10592 { my $spec = lc $_[1];
87 4159 50       6901 $spec = 'text/plain' if $spec eq 'text'; # old mailers
88              
89 4159 50       14586 $spec =~ m!^(?:x\-)?([^/]+)/(?:x-)?(.*)!
90             or return;
91              
92 4159 50       10057 my $section = $typedb{$1} or return;
93 4159 50       10881 my $record = $section->{$2} or return;
94 4159 100       9238 return $record if ref $record; # already extended
95              
96 2080         3192 my $simple = $2;
97 2080         6553 my ($type, $ext, $enc) = split m/\;/, $record;
98 2080         3290 my $os = undef; # XXX TODO
99              
100 2080         6757 $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 27     27 1 864 { my ($self, $name) = @_;
111 27         143 (my $ext = lc $name) =~ s/.*\.//;
112 27 100       105 my $type = $typedb{EXTENSIONS}{$ext} or return;
113 25         56 $self->type($type);
114             }
115              
116              
117             sub addType(@)
118 3     3 1 50 { my $self = shift;
119              
120 3         8 foreach my $type (@_)
121 3         8 { my ($major, $minor) = split m!/!, $type->simplified;
122 3         14 $typedb{$major}{$minor} = $type;
123 3         8 $typedb{EXTENSIONS}{$_} = $type for $type->extensions;
124             }
125 3         10 $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 10 { my $self = shift;
143 6         10 my @types;
144 6         62 foreach my $section (keys %typedb)
145 138 100       280 { next if $section eq 'EXTENSIONS';
146 132         163 foreach my $sub (sort keys %{$typedb{$section}})
  132         14150  
147 18246         34536 { my $record = $typedb{$section}{$sub};
148 18246 50       51018 push @types, ref $record ? $record->type
    100          
149             : $record =~ m/^([^;]+)/ ? $1 : die;
150             }
151             }
152 6         23222 @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 3646 { my $self = shift;
163 7         11 my @listed;
164              
165 7         39 foreach (split /\,\s*/, shift)
166             {
167 17 50       88 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         55 my $mime = "$1/$2$4";
173 17 100       36 my $q = defined $3 ? $3 : 1; # q, default=1
174              
175             # most complex first
176 17 100       54 $q += $4 ? +0.01 : $1 eq '*' ? -0.02 : $2 eq '*' ? -0.01 : 0;
    100          
    50          
177              
178             # keep order
179 17         34 $q -= @listed*0.0001;
180              
181 17         39 push @listed, [ $mime => $q ];
182             }
183 7         35 map $_->[0], sort {$b->[1] <=> $a->[1]} @listed;
  15         53  
184             }
185              
186              
187             sub httpAcceptBest($@)
188 8     8 1 1250 { my $self = shift;
189 8 100       25 my @accept = ref $_[0] eq 'ARRAY' ? @{(shift)} : $self->httpAccept(shift);
  4         8  
190 8         11 my $match;
191              
192 8         14 foreach my $acc (@accept)
193 10         18 { $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   56 : first { $_->mediaType eq $acc } @_;
  0 50       0  
197 10 100       55 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       10 unless(defined $accept)
209 1         2 { my $fn = $fns->[0];
210 1         4 return ($fn, $self->mimeTypeOf($fn));
211             }
212              
213             # create mapping type -> filename
214 3         6 my (%have, @have);
215 3         6 foreach my $fn (@$fns)
216 6 50       12 { 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       19 defined $type ? ($have{$type}, $type) : ();
223             }
224              
225             #-------------------------------------------
226             # OLD INTERFACE (version 0.06 and lower)
227              
228              
229 4     4   34 use base 'Exporter';
  4         9  
  4         1963  
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 7894 { my $filename = shift;
237 7   66     34 $mime_types ||= MIME::Types->new;
238 7         26 my $mime = $mime_types->mimeTypeOf($filename);
239              
240 7 100       25 my @data = defined $mime ? ($mime->type, $mime->encoding) : ('','');
241 7 100       30 wantarray ? @data : \@data;
242             }
243              
244              
245             sub by_mediatype($)
246 8     8 1 18123 { my $type = shift;
247 8   33     25 $mime_types ||= MIME::Types->new;
248              
249 8         16 my @found;
250 8 100 100     52 if(!ref $type && index($type, '/') >= 0)
251 2         7 { my $mime = $mime_types->type($type);
252 2 50       7 @found = $mime if $mime;
253             }
254             else
255 6 100       92 { my $search = ref $type eq 'Regexp' ? $type : qr/$type/i;
256 6         26 @found = map $mime_types->type($_),
257             grep $_ =~ $search,
258             $mime_types->listTypes;
259             }
260              
261 8         1573 my @data;
262 8         32 foreach my $mime (@found)
263 4126         6814 { push @data, map [$_, $mime->type, $mime->encoding],
264             $mime->extensions;
265             }
266              
267 8 100       1264 wantarray ? @data : \@data;
268             }
269              
270              
271             sub import_mime_types($)
272 0     0 1   { my $filename = shift;
273 4     4   30 use Carp;
  4         8  
  4         444  
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;