1package URI::file; 2 3use strict; 4use vars qw(@ISA $VERSION $DEFAULT_AUTHORITY %OS_CLASS); 5 6require URI::_generic; 7@ISA = qw(URI::_generic); 8$VERSION = sprintf("%d.%02d", q$Revision: 4.19 $ =~ /(\d+)\.(\d+)/); 9 10use 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 27sub 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 40sub path { shift->path_query(@_) } 41sub host { uri_unescape(shift->authority(@_)) } 42 43sub new 44{ 45 my($class, $path, $os) = @_; 46 os_class($os)->new($path); 47} 48 49sub 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 57sub 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 68sub 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 95sub file 96{ 97 my($self, $os) = @_; 98 os_class($os)->file($self); 99} 100 101sub dir 102{ 103 my($self, $os) = @_; 104 os_class($os)->dir($self); 105} 106 1071; 108 109__END__ 110 111=head1 NAME 112 113URI::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 130The C<URI::file> class supports C<URI> objects belonging to the I<file> 131URI scheme. This scheme allows us to map the conventional file names 132found on various computer systems to the URI name space. An old 133specification of the I<file> URI scheme is found in RFC 1738. Some 134older background information is also in RFC 1630. There are no newer 135specifications as far as I know. 136 137If you simply want to construct I<file> URI objects from URI strings, 138use the normal C<URI> constructor. If you want to construct I<file> 139URI objects from the actual file names used by various systems, then 140use one of the following C<URI::file> constructors: 141 142=over 4 143 144=item $u = URI::file->new( $filename, [$os] ) 145 146Maps a file name to the I<file:> URI name space, creates a URI object 147and returns it. The $filename is interpreted as belonging to the 148indicated operating system ($os), which defaults to the value of the 149$^O variable. The $filename can be either absolute or relative, and 150the corresponding type of URI object for $os is returned. 151 152=item $u = URI::file->new_abs( $filename, [$os] ) 153 154Same as URI::file->new, but makes sure that the URI returned 155represents an absolute file name. If the $filename argument is 156relative, then the name is resolved relative to the current directory, 157i.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 163Returns a I<file> URI that represents the current working directory. 164See L<Cwd>. 165 166=back 167 168The following methods are supported for I<file> URI (in addition to 169the common and generic methods described in L<URI>): 170 171=over 4 172 173=item $u->file( [$os] ) 174 175Returns a file name. It maps from the URI name space 176to the file name space of the indicated operating system. 177 178It might return C<undef> if the name can not be represented in the 179indicated file system. 180 181=item $u->dir( [$os] ) 182 183Some systems use a different form for names of directories than for plain 184files. Use this method if you know you want to use the name for 185a directory. 186 187=back 188 189The C<URI::file> module can be used to map generic file names to names 190suitable for the current system. As such, it can work as a nice 191replacement for the C<File::Spec> module. For instance, the following 192code translates the UNIX-style file name F<Foo/Bar.pm> to a name 193suitable 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 202Most computer systems today have hierarchically organized file systems. 203Mapping the names used in these systems to the generic URI syntax 204allows us to work with relative file URIs that behave as they should 205when resolved using the generic algorithm for URIs (specified in RFC 2062396). Mapping a file name to the generic URI syntax involves mapping 207the path separator character to "/" and encoding any reserved 208characters that appear in the path segments of the file name. If 209path segments consisting of the strings "." or ".." have a 210different meaning than what is specified for generic URIs, then these 211must be encoded as well. 212 213If the file system has device, volume or drive specifications as 214the root of the name space, then it makes sense to map them to the 215authority field of the generic URI syntax. This makes sure that 216relative URIs can not be resolved "above" them, i.e. generally how 217relative file names work in those systems. 218 219Another common use of the authority field is to encode the host on which 220this file name is valid. The host name "localhost" is special and 221generally has the same meaning as a missing or empty authority 222field. This use is in conflict with using it as a device 223specification, but can often be resolved for device specifications 224having characters not legal in plain host names. 225 226File name to URI mapping in normally not one-to-one. There are 227usually many URIs that map to any given file name. For instance, an 228authority of "localhost" maps the same as a URI with a missing or empty 229authority. 230 231Example 1: The Mac uses ":" as path separator, but not in the same way 232as a generic URI. ":foo" is a relative name. "foo:bar" is an absolute 233name. Also, path segments can contain the "/" character as well as the 234literal "." 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 249Note that if you want a relative URL, you *must* begin the path with a :. Any 250path that begins with [^:] is treated as absolute. 251 252Example 2: The UNIX file system is easy to map, as it uses the same path 253separator as URIs, has a single root, and segments of "." and ".." 254have the same meaning. URIs that have the character "\0" or "/" as 255part 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 269RFC 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 distribted 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 291The following configuration variables influence how the class and its 292methods behave: 293 294=over 295 296=item %URI::file::OS_CLASS 297 298This hash maps OS identifiers to implementation classes. You might 299want to add or modify this if you want to plug in your own file 300handler class. Normally the keys should match the $^O values in use. 301 302If there is no mapping then the "Unix" implementation is used. 303 304=item $URI::file::DEFAULT_AUTHORITY 305 306This determine what "authority" string to include in absolute file 307URIs. It defaults to "". If you prefer verbose URIs you might set it 308to be "localhost". 309 310Setting this value to C<undef> force behaviour compatible to URI v1.31 311and earlier. In this mode host names in UNC paths and drive letters 312are mapped to the authority component on Windows, while we produce 313authority-less URIs on Unix. 314 315=back 316 317 318=head1 SEE ALSO 319 320L<URI>, L<File::Spec>, L<perlport> 321 322=head1 COPYRIGHT 323 324Copyright 1995-1998,2004 Gisle Aas. 325 326This library is free software; you can redistribute it and/or 327modify it under the same terms as Perl itself. 328 329=cut 330