Commit | Line | Data |
3fea05b9 |
1 | package URI::file; |
2 | |
3 | use strict; |
4 | use vars qw(@ISA $VERSION $DEFAULT_AUTHORITY %OS_CLASS); |
5 | |
6 | require URI::_generic; |
7 | @ISA = qw(URI::_generic); |
8 | $VERSION = "4.20"; |
9 | |
10 | use URI::Escape qw(uri_unescape); |
11 | |
12 | $DEFAULT_AUTHORITY = ""; |
13 | |
14 | # Map from $^O values to implementation classes. The Unix |
15 | # class is the default. |
16 | %OS_CLASS = ( |
17 | os2 => "OS2", |
18 | mac => "Mac", |
19 | MacOS => "Mac", |
20 | MSWin32 => "Win32", |
21 | win32 => "Win32", |
22 | msdos => "FAT", |
23 | dos => "FAT", |
24 | qnx => "QNX", |
25 | ); |
26 | |
27 | sub os_class |
28 | { |
29 | my($OS) = shift || $^O; |
30 | |
31 | my $class = "URI::file::" . ($OS_CLASS{$OS} || "Unix"); |
32 | no strict 'refs'; |
33 | unless (%{"$class\::"}) { |
34 | eval "require $class"; |
35 | die $@ if $@; |
36 | } |
37 | $class; |
38 | } |
39 | |
40 | sub path { shift->path_query(@_) } |
41 | sub host { uri_unescape(shift->authority(@_)) } |
42 | |
43 | sub new |
44 | { |
45 | my($class, $path, $os) = @_; |
46 | os_class($os)->new($path); |
47 | } |
48 | |
49 | sub new_abs |
50 | { |
51 | my $class = shift; |
52 | my $file = $class->new(@_); |
53 | return $file->abs($class->cwd) unless $$file =~ /^file:/; |
54 | $file; |
55 | } |
56 | |
57 | sub cwd |
58 | { |
59 | my $class = shift; |
60 | require Cwd; |
61 | my $cwd = Cwd::cwd(); |
62 | $cwd = VMS::Filespec::unixpath($cwd) if $^O eq 'VMS'; |
63 | $cwd = $class->new($cwd); |
64 | $cwd .= "/" unless substr($cwd, -1, 1) eq "/"; |
65 | $cwd; |
66 | } |
67 | |
68 | sub canonical { |
69 | my $self = shift; |
70 | my $other = $self->SUPER::canonical; |
71 | |
72 | my $scheme = $other->scheme; |
73 | my $auth = $other->authority; |
74 | return $other if !defined($scheme) && !defined($auth); # relative |
75 | |
76 | if (!defined($auth) || |
77 | $auth eq "" || |
78 | lc($auth) eq "localhost" || |
79 | (defined($DEFAULT_AUTHORITY) && lc($auth) eq lc($DEFAULT_AUTHORITY)) |
80 | ) |
81 | { |
82 | # avoid cloning if $auth already match |
83 | if ((defined($auth) || defined($DEFAULT_AUTHORITY)) && |
84 | (!defined($auth) || !defined($DEFAULT_AUTHORITY) || $auth ne $DEFAULT_AUTHORITY) |
85 | ) |
86 | { |
87 | $other = $other->clone if $self == $other; |
88 | $other->authority($DEFAULT_AUTHORITY); |
89 | } |
90 | } |
91 | |
92 | $other; |
93 | } |
94 | |
95 | sub file |
96 | { |
97 | my($self, $os) = @_; |
98 | os_class($os)->file($self); |
99 | } |
100 | |
101 | sub dir |
102 | { |
103 | my($self, $os) = @_; |
104 | os_class($os)->dir($self); |
105 | } |
106 | |
107 | 1; |
108 | |
109 | __END__ |
110 | |
111 | =head1 NAME |
112 | |
113 | URI::file - URI that maps to local file names |
114 | |
115 | =head1 SYNOPSIS |
116 | |
117 | use URI::file; |
118 | |
119 | $u1 = URI->new("file:/foo/bar"); |
120 | $u2 = URI->new("foo/bar", "file"); |
121 | |
122 | $u3 = URI::file->new($path); |
123 | $u4 = URI::file->new("c:\\windows\\", "win32"); |
124 | |
125 | $u1->file; |
126 | $u1->file("mac"); |
127 | |
128 | =head1 DESCRIPTION |
129 | |
130 | The C<URI::file> class supports C<URI> objects belonging to the I<file> |
131 | URI scheme. This scheme allows us to map the conventional file names |
132 | found on various computer systems to the URI name space. An old |
133 | specification of the I<file> URI scheme is found in RFC 1738. Some |
134 | older background information is also in RFC 1630. There are no newer |
135 | specifications as far as I know. |
136 | |
137 | If you simply want to construct I<file> URI objects from URI strings, |
138 | use the normal C<URI> constructor. If you want to construct I<file> |
139 | URI objects from the actual file names used by various systems, then |
140 | use one of the following C<URI::file> constructors: |
141 | |
142 | =over 4 |
143 | |
144 | =item $u = URI::file->new( $filename, [$os] ) |
145 | |
146 | Maps a file name to the I<file:> URI name space, creates a URI object |
147 | and returns it. The $filename is interpreted as belonging to the |
148 | indicated operating system ($os), which defaults to the value of the |
149 | $^O variable. The $filename can be either absolute or relative, and |
150 | the corresponding type of URI object for $os is returned. |
151 | |
152 | =item $u = URI::file->new_abs( $filename, [$os] ) |
153 | |
154 | Same as URI::file->new, but makes sure that the URI returned |
155 | represents an absolute file name. If the $filename argument is |
156 | relative, then the name is resolved relative to the current directory, |
157 | i.e. this constructor is really the same as: |
158 | |
159 | URI::file->new($filename)->abs(URI::file->cwd); |
160 | |
161 | =item $u = URI::file->cwd |
162 | |
163 | Returns a I<file> URI that represents the current working directory. |
164 | See L<Cwd>. |
165 | |
166 | =back |
167 | |
168 | The following methods are supported for I<file> URI (in addition to |
169 | the common and generic methods described in L<URI>): |
170 | |
171 | =over 4 |
172 | |
173 | =item $u->file( [$os] ) |
174 | |
175 | Returns a file name. It maps from the URI name space |
176 | to the file name space of the indicated operating system. |
177 | |
178 | It might return C<undef> if the name can not be represented in the |
179 | indicated file system. |
180 | |
181 | =item $u->dir( [$os] ) |
182 | |
183 | Some systems use a different form for names of directories than for plain |
184 | files. Use this method if you know you want to use the name for |
185 | a directory. |
186 | |
187 | =back |
188 | |
189 | The C<URI::file> module can be used to map generic file names to names |
190 | suitable for the current system. As such, it can work as a nice |
191 | replacement for the C<File::Spec> module. For instance, the following |
192 | code translates the UNIX-style file name F<Foo/Bar.pm> to a name |
193 | suitable for the local system: |
194 | |
195 | $file = URI::file->new("Foo/Bar.pm", "unix")->file; |
196 | die "Can't map filename Foo/Bar.pm for $^O" unless defined $file; |
197 | open(FILE, $file) || die "Can't open '$file': $!"; |
198 | # do something with FILE |
199 | |
200 | =head1 MAPPING NOTES |
201 | |
202 | Most computer systems today have hierarchically organized file systems. |
203 | Mapping the names used in these systems to the generic URI syntax |
204 | allows us to work with relative file URIs that behave as they should |
205 | when resolved using the generic algorithm for URIs (specified in RFC |
206 | 2396). Mapping a file name to the generic URI syntax involves mapping |
207 | the path separator character to "/" and encoding any reserved |
208 | characters that appear in the path segments of the file name. If |
209 | path segments consisting of the strings "." or ".." have a |
210 | different meaning than what is specified for generic URIs, then these |
211 | must be encoded as well. |
212 | |
213 | If the file system has device, volume or drive specifications as |
214 | the root of the name space, then it makes sense to map them to the |
215 | authority field of the generic URI syntax. This makes sure that |
216 | relative URIs can not be resolved "above" them, i.e. generally how |
217 | relative file names work in those systems. |
218 | |
219 | Another common use of the authority field is to encode the host on which |
220 | this file name is valid. The host name "localhost" is special and |
221 | generally has the same meaning as a missing or empty authority |
222 | field. This use is in conflict with using it as a device |
223 | specification, but can often be resolved for device specifications |
224 | having characters not legal in plain host names. |
225 | |
226 | File name to URI mapping in normally not one-to-one. There are |
227 | usually many URIs that map to any given file name. For instance, an |
228 | authority of "localhost" maps the same as a URI with a missing or empty |
229 | authority. |
230 | |
231 | Example 1: The Mac uses ":" as path separator, but not in the same way |
232 | as a generic URI. ":foo" is a relative name. "foo:bar" is an absolute |
233 | name. Also, path segments can contain the "/" character as well as the |
234 | literal "." or "..". So the mapping looks like this: |
235 | |
236 | Mac URI |
237 | ---------- ------------------- |
238 | :foo:bar <==> foo/bar |
239 | : <==> ./ |
240 | ::foo:bar <==> ../foo/bar |
241 | ::: <==> ../../ |
242 | foo:bar <==> file:/foo/bar |
243 | foo:bar: <==> file:/foo/bar/ |
244 | .. <==> %2E%2E |
245 | <undef> <== / |
246 | foo/ <== file:/foo%2F |
247 | ./foo.txt <== file:/.%2Ffoo.txt |
248 | |
249 | Note that if you want a relative URL, you *must* begin the path with a :. Any |
250 | path that begins with [^:] is treated as absolute. |
251 | |
252 | Example 2: The UNIX file system is easy to map, as it uses the same path |
253 | separator as URIs, has a single root, and segments of "." and ".." |
254 | have the same meaning. URIs that have the character "\0" or "/" as |
255 | part of any path segment can not be turned into valid UNIX file names. |
256 | |
257 | UNIX URI |
258 | ---------- ------------------ |
259 | foo/bar <==> foo/bar |
260 | /foo/bar <==> file:/foo/bar |
261 | /foo/bar <== file://localhost/foo/bar |
262 | file: ==> ./file: |
263 | <undef> <== file:/fo%00/bar |
264 | / <==> file:/ |
265 | |
266 | =cut |
267 | |
268 | |
269 | RFC 1630 |
270 | |
271 | [...] |
272 | |
273 | There is clearly a danger of confusion that a link made to a local |
274 | file should be followed by someone on a different system, with |
275 | unexpected and possibly harmful results. Therefore, the convention |
276 | is that even a "file" URL is provided with a host part. This allows |
277 | a client on another system to know that it cannot access the file |
278 | system, or perhaps to use some other local mechanism to access the |
279 | file. |
280 | |
281 | The special value "localhost" is used in the host field to indicate |
282 | that the filename should really be used on whatever host one is. |
283 | This for example allows links to be made to files which are |
284 | distributed on many machines, or to "your unix local password file" |
285 | subject of course to consistency across the users of the data. |
286 | |
287 | A void host field is equivalent to "localhost". |
288 | |
289 | =head1 CONFIGURATION VARIABLES |
290 | |
291 | The following configuration variables influence how the class and its |
292 | methods behave: |
293 | |
294 | =over |
295 | |
296 | =item %URI::file::OS_CLASS |
297 | |
298 | This hash maps OS identifiers to implementation classes. You might |
299 | want to add or modify this if you want to plug in your own file |
300 | handler class. Normally the keys should match the $^O values in use. |
301 | |
302 | If there is no mapping then the "Unix" implementation is used. |
303 | |
304 | =item $URI::file::DEFAULT_AUTHORITY |
305 | |
306 | This determine what "authority" string to include in absolute file |
307 | URIs. It defaults to "". If you prefer verbose URIs you might set it |
308 | to be "localhost". |
309 | |
310 | Setting this value to C<undef> force behaviour compatible to URI v1.31 |
311 | and earlier. In this mode host names in UNC paths and drive letters |
312 | are mapped to the authority component on Windows, while we produce |
313 | authority-less URIs on Unix. |
314 | |
315 | =back |
316 | |
317 | |
318 | =head1 SEE ALSO |
319 | |
320 | L<URI>, L<File::Spec>, L<perlport> |
321 | |
322 | =head1 COPYRIGHT |
323 | |
324 | Copyright 1995-1998,2004 Gisle Aas. |
325 | |
326 | This library is free software; you can redistribute it and/or |
327 | modify it under the same terms as Perl itself. |
328 | |
329 | =cut |