fixed URI::URL rel
Thomas J. Popovich (tpop@zso.dec.com)
Sat, 15 Aug 1998 21:50:23 -0700
$r2 = new URI::URL
'http://www.zc.com/AddingSecurityIntoM2.html#Figure1',
'http://www.zc.com/~foo/security/Adding.html#Figure1';
print $r2->rel, "\n";
will print out ../../AddingSecurityIntoM2.html#Figure1
I think that this should NOT map to ../../XXX since you don't know
where/what ~foo maps to. This should stay mapped to:
http://www.zc.com/AddingSecurityIntoM2.html.
=======================================
its fixed in the following code
package URI::URL::_generic;
# The oposite of $url->abs. Return a URL as much relative as possible
sub rel {
my($self, $base) = @_;
my $rel = $self->clone;
$base = $self->base unless $base;
return $rel unless $base;
$base = new URI::URL $base unless ref $base;
$rel->base($base);
my($scheme, $netloc, $path) = @{$rel}{qw(scheme netloc path)};
if (!defined($scheme) && !defined($netloc)) {
# it is already relative
return $rel;
}
my($bscheme, $bnetloc, $bpath) = @{$base}{qw(scheme netloc path)};
for ($bscheme, $bnetloc, $netloc) { $_ = '' unless defined }
unless ($scheme eq $bscheme && $netloc eq $bnetloc) {
# different location, can't make it relative
return $rel;
}
## if you have 2 paths to compare like
## $bpath=/~foo/security/Adding.html and $path=/AddingSecurityIntoM2.html
## the original rel would return 'a relative path path'
## of => '../../AddingSecurityIntoM2.html'
## The following code will cause an absolute path to be returned instead
return $rel
if (($bpath =~ m, ^ (?# start of path) /~ (?# then / & ~) ,x)
|| (path =~ m, ^ (?# start of path) /~ (?# then / & ~) ,x)) ;
for ($path, $bpath) { $_ = "/$_" unless m,^/,; }
# Make it relative by eliminating scheme and netloc
$rel->{'scheme'} = undef;
$rel->netloc(undef);
# This loop is based on code from Nicolai Langfeldt <janl@ifi.uio.no>.
# First we calculate common initial path components length ($li).
my $li = 1;
while (1) {
my $i = index($path, '/', $li);
last if $i < 0 ||
$i != index($bpath, '/', $li) ||
substr($path,$li,$i-$li) ne substr($bpath,$li,$i-$li);
$li=$i+1;
}
# then we nuke it from both paths
substr($path, 0,$li) = '';
substr($bpath,0,$li) = '';
if ($path eq $bpath && defined($rel->frag) && !defined($rel->equery)) {
$rel->epath('');
} else {
# Add one "../" for each path component left in the base path
$path = ('../' x $bpath =~ tr|/|/|) . $path;
$path = "./" if $path eq "";
$rel->epath($path);
}
$rel;
}