File Coverage

blib/lib/File/MimeInfo/Applications.pm
Criterion Covered Total %
statement 59 120 49.1
branch 11 50 22.0
condition 4 12 33.3
subroutine 11 17 64.7
pod 4 4 100.0
total 89 203 43.8


line stmt bran cond sub pod time code
1             package File::MimeInfo::Applications;
2              
3 3     3   26542 use strict;
  3         28  
  3         115  
4 3     3   15 use warnings;
  3         5  
  3         151  
5 3     3   16 use Carp;
  3         6  
  3         229  
6 3     3   16 use File::Spec;
  3         4  
  3         108  
7 3     3   13 use File::BaseDir qw/config_home config_dirs data_home data_dirs data_files/;
  3         6  
  3         221  
8 3     3   16 use File::MimeInfo qw/mimetype_canon mimetype_isa/;
  3         6  
  3         184  
9 3     3   646 use File::DesktopEntry;
  3         11063  
  3         4625  
10             require Exporter;
11              
12             our $VERSION = '0.36';
13              
14             our @ISA = qw(Exporter);
15             our @EXPORT = qw(
16             mime_applications mime_applications_all
17             mime_applications_set_default mime_applications_set_custom
18             );
19              
20             print STDERR << 'EOT' unless data_files(qw/applications mimeinfo.cache/);
21             WARNING: You don't seem to have any mimeinfo.cache files.
22             Try running the update-desktop-database command. If you
23             don't have this command you should install the
24             desktop-file-utils package. This package is available from
25             http://freedesktop.org/wiki/Software/desktop-file-utils/
26             EOT
27              
28             sub mime_applications {
29 2 50   2 1 1443 croak "usage: mime_applications(MIMETYPE)" unless @_ == 1;
30 2         9 my $mime = mimetype_canon(shift @_);
31 2         5 local $Carp::CarpLevel = $Carp::CarpLevel + 1;
32 2 50       7 return wantarray ? (_default($mime), _others($mime)) : _default($mime);
33             }
34              
35             sub mime_applications_all {
36 0 0   0 1 0 croak "usage: mime_applications(MIMETYPE)" unless @_ == 1;
37 0         0 my $mime = shift;
38 0         0 return mime_applications($mime),
39             grep defined($_), map mime_applications($_), mimetype_isa($mime);
40             }
41              
42             sub mime_applications_set_default {
43 0 0   0 1 0 croak "usage: mime_applications_set_default(MIMETYPE, APPLICATION)"
44             unless @_ == 2;
45 0         0 my ($mimetype, $desktop_file) = @_;
46             (undef, undef, $desktop_file) =
47             File::Spec->splitpath($desktop_file->{file})
48 0 0       0 if ref $desktop_file;
49 0 0       0 croak "missing desktop entry filename for application"
50             unless length $desktop_file;
51 0 0       0 $desktop_file .= '.desktop' unless $desktop_file =~ /\.desktop$/;
52 0         0 _write_list($mimetype, $desktop_file);
53             }
54              
55             sub mime_applications_set_custom {
56 0 0   0 1 0 croak "usage: mime_applications_set_custom(MIMETYPE, COMMAND)"
57             unless @_ == 2;
58 0         0 my ($mimetype, $command) = @_;
59 0         0 $command =~ /(\w+)/;
60 0 0       0 my $word = $1 or croak "COMMAND does not contain a word !?";
61              
62             # Algorithm to generate name copied from other implementations
63 0         0 my $i = 1;
64 0         0 my $desktop_file =
65             data_home('applications', $word.'-usercreated-'.$i.'.desktop');
66 0         0 while (-e $desktop_file) {
67 0         0 $i++;
68 0         0 $desktop_file =
69             data_home('applications', $word.'-usercreated-'.$i.'.desktop');
70             }
71              
72 0         0 my $object = File::DesktopEntry->new();
73 0         0 $object->set(
74             Type => 'Application',
75             Name => $word,
76             NoDisplay => 'true',
77             Exec => $command,
78             );
79 0         0 my (undef, undef, $df) = File::Spec->splitpath($desktop_file);
80 0         0 _write_list($mimetype, $df); # creates dir if needed
81 0         0 $object->write($desktop_file);
82 0         0 return $object;
83             }
84              
85             sub _default {
86 2     2   2 my $mimetype = shift;
87              
88 2         6 my $user = config_home(qw/mimeapps.list/);
89 2         55 my $system = config_dirs(qw/mimeapps.list/);
90 2         210 my $deprecated = data_home(qw/applications mimeapps.list/);
91 2         30 my $distro = data_dirs(qw/applications mimeapps.list/);
92 2         139 my $legacy = data_home(qw/applications defaults.list/);
93              
94 2 50 33     65 unless ( ( -f $user
      33        
95             || ($system && -f $system)
96             || ($deprecated && -f $deprecated)
97             || ($distro && -f $distro)
98             || ($legacy && -f $legacy) )
99             && -r _ ) {
100 2         6 return undef;
101             }
102              
103 0         0 $Carp::CarpLevel++;
104 0         0 my @paths = grep defined, ($mimetype, $user, $system, $deprecated, $distro, $legacy);
105 0         0 my @list = _read_list(@paths);
106 0 0       0 return undef if @list == 0;
107 0         0 my $desktop_file = _find_file(reverse @list);
108 0         0 $Carp::CarpLevel--;
109              
110 0         0 return $desktop_file;
111             }
112              
113             sub _others {
114 2     2   23 my $mimetype = shift;
115              
116 2         3 $Carp::CarpLevel++;
117 2         2 my (@list, @done);
118 2         5 for my $dir (data_dirs('applications')) {
119 4         165 my $cache = File::Spec->catfile($dir, 'mimeinfo.cache');
120 4 100       10 next if grep {$_ eq $cache} @done;
  2         6  
121 2         2 push @done, $cache;
122 2 50 33     22 next unless -f $cache and -r _;
123 2         5 for (_read_list($mimetype, $cache)) {
124 2         15 my $file = File::Spec->catfile($dir, $_);
125 2 50 33     49 next unless -f $file and -r _;
126 2         10 push @list, File::DesktopEntry->new($file);
127             }
128             }
129 2         4 $Carp::CarpLevel--;
130              
131 2         8 return @list;
132             }
133              
134             sub _read_list { # read list with "mime/type=foo.desktop;bar.desktop" format
135 2     2   2 my $mimetype = shift;
136              
137 2         3 my @list;
138             my $succeeded;
139              
140 2         4 for my $file (@_) {
141 2 50       51 if (open LIST, '<', $file) {
142 2         3 $succeeded = 1;
143 2         52 while () {
144 6 100       66 /^\Q$mimetype\E=(.*)$/ or next;
145 2         15 push @list, grep defined($_), split ';', $1;
146             }
147 2         18 close LIST;
148             }
149             }
150              
151 2 50       4 unless ($succeeded) {
152 0         0 croak "Could not read any defaults, tried:\n" . join("\t\n", @_);
153             }
154              
155 2         5 return @list;
156             }
157              
158             sub _write_list {
159 0     0     my ($mimetype, $desktop_file) = @_;
160 0           my $file = config_home(qw/mimeapps.list/);
161 0           my $text;
162 0 0         if (-f $file) {
163 0 0         open LIST, '<', $file or croak "Could not read file: $file";
164 0           while () {
165 0 0         $text .= $_ unless /^\Q$mimetype\E=/;
166             }
167 0           close LIST;
168 0           $text =~ s/[\n\r]?$/\n/; # just to be sure
169             }
170             else {
171 0           _mkdir($file);
172 0           $text = "[Default Applications]\n";
173             }
174              
175 0 0         open LIST, '>', $file or croak "Could not write file: $file";
176 0           print LIST $text;
177 0           print LIST "$mimetype=$desktop_file;\n";
178 0 0         close LIST or croak "Could not write file: $file";
179             }
180              
181             sub _find_file {
182 0     0     my @list = @_;
183 0           for (@list) {
184 0           my $file = data_files('applications', $_);
185 0 0         return File::DesktopEntry->new($file) if $file;
186             }
187 0           return undef;
188             }
189              
190             sub _mkdir {
191 0     0     my $dir = shift;
192 0 0         return if -d $dir;
193              
194 0           my ($vol, $dirs, undef) = File::Spec->splitpath($dir);
195 0           my @dirs = File::Spec->splitdir($dirs);
196 0           my $path = File::Spec->catpath($vol, shift @dirs);
197 0           while (@dirs) {
198 0           mkdir $path; # fails silently
199 0           $path = File::Spec->catdir($path, shift @dirs);
200             }
201              
202 0 0         die "Could not create dir: $path\n" unless -d $path;
203             }
204              
205             1;
206              
207             __END__