1package File::BaseDir;
2
3use strict;
4use Carp;
5require File::Spec;
6require Exporter;
7
8our $VERSION = 0.07;
9
10our @ISA = qw(Exporter);
11our %EXPORT_TAGS = (
12	vars => [ qw(
13		xdg_data_home xdg_data_dirs
14		xdg_config_home xdg_config_dirs
15		xdg_cache_home
16	) ],
17	lookup => [ qw(
18		data_home data_dirs data_files
19		config_home config_dirs config_files
20		cache_home
21	) ],
22);
23our @EXPORT_OK = (
24	qw(xdg_data_files xdg_config_files),
25	map @$_, values %EXPORT_TAGS
26);
27
28# Set root and home directories
29my $rootdir = File::Spec->rootdir();
30if ($^O eq 'MSWin32') {
31	$rootdir = 'C:\\'; # File::Spec default depends on CWD
32	$ENV{HOME} ||= $ENV{USERPROFILE} || $ENV{HOMEDRIVE}.$ENV{HOMEPATH};
33		# logic from File::HomeDir::Windows
34}
35my $home = $ENV{HOME};
36unless ($home) {
37	# Default to  operating system's home dir. NOTE: web applications may not have $ENV{HOME} assigned,
38	# so don't issue a warning. See RT bug #41744
39	$home = $rootdir;
40}
41
42# Set defaults
43our $xdg_data_home = File::Spec->catdir($home, qw/.local share/);
44our @xdg_data_dirs = (
45	File::Spec->catdir($rootdir, qw/usr local share/),
46	File::Spec->catdir($rootdir, qw/usr share/),
47);
48our $xdg_config_home = File::Spec->catdir($home, '.config');
49our @xdg_config_dirs = ( File::Spec->catdir($rootdir, qw/etc xdg/) );
50our $xdg_cache_home = File::Spec->catdir($home, '.cache');
51
52# OO method
53sub new { bless \$VERSION, shift } # what else is there to bless ?
54
55# Variable methods
56sub xdg_data_home { $ENV{XDG_DATA_HOME} || $xdg_data_home }
57
58sub xdg_data_dirs {
59	( $ENV{XDG_DATA_DIRS}
60		? _adapt($ENV{XDG_DATA_DIRS})
61		: @xdg_data_dirs
62	)
63}
64
65sub xdg_config_home {$ENV{XDG_CONFIG_HOME} || $xdg_config_home }
66
67sub xdg_config_dirs {
68	( $ENV{XDG_CONFIG_DIRS}
69		? _adapt($ENV{XDG_CONFIG_DIRS})
70		: @xdg_config_dirs
71	)
72}
73
74sub xdg_cache_home { $ENV{XDG_CACHE_HOME} || $xdg_cache_home }
75
76sub _adapt {
77	map { File::Spec->catdir( split('/', $_) ) } split /[:;]/, shift;
78		# ':' defined in the spec, but ';' is standard on win32
79}
80
81# Lookup methods
82sub data_home { _catfile(xdg_data_home, @_) }
83
84sub data_dirs { _find_files(\&_dir, \@_, xdg_data_home, xdg_data_dirs) }
85
86sub data_files { _find_files(\&_file, \@_, xdg_data_home, xdg_data_dirs) }
87
88sub xdg_data_files { my @dirs = data_files(@_); return @dirs }
89
90sub config_home { _catfile(xdg_config_home, @_) }
91
92sub config_dirs { _find_files(\&_dir, \@_, xdg_config_home, xdg_config_dirs) }
93
94sub config_files { _find_files(\&_file, \@_, xdg_config_home, xdg_config_dirs) }
95
96sub xdg_config_files { my @dirs = config_files(@_); return @dirs }
97
98sub cache_home { _catfile(xdg_cache_home, @_) }
99
100sub _catfile {
101	my $dir = shift;
102	shift if ref $_[0] or $_[0] =~ /::/; # OO call
103	return File::Spec->catfile($dir, @_);
104}
105
106sub _find_files {
107	my $type = shift;
108	my $file = shift;
109	shift @$file if ref $$file[0] or $$file[0] =~ /::/; # OO call
110	#warn "Looking for: @$file\n         in: @_\n";
111	if (wantarray) {
112		return grep { &$type( $_ ) && -r $_ }
113		       map  { File::Spec->catfile($_, @$file) } @_;
114	}
115	else { # prevent unnecessary stats by returning early
116		for (@_) {
117			my $path = File::Spec->catfile($_, @$file);
118			return $path if &$type($path) && -r $path;
119		}
120	}
121	return ();
122}
123
124sub _dir { -d $_[0] }
125
126sub _file { -f $_[0] }
127
1281;
129
130__END__
131
132=head1 NAME
133
134File::BaseDir - Use the Freedesktop.org base directory specification
135
136=head1 SYNOPSIS
137
138	use File::BaseDir qw/xdg_data_files/;
139	for ( xdg_data_files('mime/globs') ) {
140		# do something
141	}
142
143=head1 DESCRIPTION
144
145This module can be used to find directories and files as specified
146by the Freedesktop.org Base Directory Specification. This specifications
147gives a mechanism to locate directories for configuration, application data
148and cache data. It is suggested that desktop applications for e.g. the
149Gnome, KDE or Xfce platforms follow this layout. However, the same layout can
150just as well be used for non-GUI applications.
151
152This module forked from L<File::MimeInfo>.
153
154This module follows version 0.6 of BaseDir specification.
155
156=head1 EXPORT
157
158None by default, but all methods can be exported on demand.
159Also the groups ":lookup" and ":vars" are defined. The ":vars" group
160contains all routines with a "xdg_" prefix; the ":lookup" group
161contains the routines to locate files and directories.
162
163=head1 METHODS
164
165=over 4
166
167=item C<new()>
168
169Simple constructor to allow Object Oriented use of this module.
170
171=back
172
173=head2 Lookup
174
175The following methods are used to lookup files and folders in one of the
176search paths.
177
178=over 4
179
180=item C<data_home(@PATH)>
181
182Takes a list of file path elements and returns a new path by appending
183them to the data home directory. The new path does not need to exist.
184Use this when writing user specific application data.
185
186Example:
187
188  # data_home is: /home/USER/.local/share
189  $path = $bd->data_home('Foo', 'Bar', 'Baz');
190  # returns: /home/USER/.local/share/Foo/Bar/Baz
191
192=item C<data_dirs(@PATH)>
193
194Looks for directories specified by C<@PATH> in the data home and
195other data directories. Returns (possibly empty) list of readable
196directories. In scalar context only the first directory found is
197returned. Use this to lookup application data.
198
199=item C<data_files(@PATH)>
200
201Looks for files specified by C<@PATH> in the data home and other data
202directories. Only returns files that are readable. In scalar context only
203the first file found is returned. Use this to lookup application data.
204
205=item C<config_home(@PATH)>
206
207Takes a list of path elements and appends them to the config home
208directory returning a new path. The new path does not need to exist.
209Use this when writing user specific configuration.
210
211=item C<config_dirs(@PATH)>
212
213Looks for directories specified by C<@PATH> in the config home and
214other config directories. Returns (possibly empty) list of readable
215directories. In scalar context only the first directory found is
216returned. Use this to lookup configuration.
217
218=item C<config_files(@PATH)>
219
220Looks for files specified by C<@PATH> in the config home and other
221config directories. Returns a (possibly empty) list of files that
222are readable. In scalar context only the first file found is returned.
223Use this to lookup configuration.
224
225=item C<cache_home(@PATH)>
226
227Takes a list of path elements and appends them to the cache home
228directory returning a new path. The new path does not need to exist.
229
230=back
231
232=head2 Variables
233
234The following methods only returns the value of one of the XDG variables.
235
236=over 4
237
238=item C<xdg_data_home>
239
240Returns either C<$ENV{XDG_DATA_HOME}> or it's default value.
241Default is F<$HOME/.local/share>.
242
243=item C<xdg_data_dirs>
244
245Returns either C<$ENV{XDG_DATA_DIRS}> or it's default value as list.
246Default is F</usr/local/share>, F</usr/share>.
247
248=item C<xdg_config_home>
249
250Returns either C<$ENV{XDG_CONFIG_HOME}> or it's default value.
251Default is F<$HOME/.config>.
252
253=item C<xdg_config_dirs>
254
255Returns either C<$ENV{XDG_CONFIG_DIRS}> or it's default value as list.
256Default is F</etc/xdg>.
257
258=item C<xdg_cache_home>
259
260Returns either C<$ENV{XDG_CACHE_HOME}> or it's default value.
261Default is F<$HOME/.cache>.
262
263=back
264
265=head1 NON-UNIX PLATFORMS
266
267The use of L<File::Spec> ensures that all paths are returned in the appropriate
268form for the current platform. On Windows this module will try to set C<$HOME>
269to a sensible value if it is not defined yet. On other platforms one can use
270e.g. L<File::HomeDir> to set $HOME before loading File::BaseDir.
271
272Please note that the specification is targeting Unix platforms only and
273will only have limited relevance on other platforms. Any platform dependent
274behavior in this module should be considered an extension of the spec.
275
276=head1 BACKWARDS COMPATIBILITY
277
278The methods C<xdg_data_files()> and C<xdg_config_files()> are exported for
279backwards compatibility with version 0.02. They are identical to C<data_files()>
280and C<config_files()> respectively but without the C<wantarray> behavior.
281
282=head1 BUGS
283
284Please mail the author if you encounter any bugs.
285
286=head1 AUTHOR
287
288Jaap Karssenberg || Pardus [Larus] E<lt>pardus@cpan.orgE<gt>
289
290Copyright (c) 2003, 2007 Jaap G Karssenberg. All rights reserved.
291This program is free software; you can redistribute it and/or
292modify it under the same terms as Perl itself.
293
294Currently being maintained by Kim Ryan
295
296=head1 SEE ALSO
297
298L<http://www.freedesktop.org/wiki/Specifications/basedir-spec>
299
300