Re: Draft of announcement message

J.E. Fritz (FRITZ@gems.vcu.edu)
Mon, 05 Jun 1995 17:50:56 -0400 (EDT)


Martijn writes:

>applying that diff fails the self test elsewhere (am I glad
>we've got them :-), try perl -w URI/URL.pm

(blush)

>We need to trace through and find exactly where what goes wrong. I'll see
>if I can fix it properly tomorrow evening. Let me know if you beat me
>to it.

One fix is to change the line in question to

  $embed->{path} = '/' . join('/', @newpath) . ($isdir && @newpath ? '/' : '');

But I have another question:  when the current code makes a relative URL
absolute, it processes ../ and ./ segments of the base path as well as
those in the relative path:

   use URI::URL;
   my $base= new URI::URL 'http://host/dir1/../dir2/file';
   my $relative= new URI::URL 'file', $base;
   my $result= $relative->abs;
   print "Base:   $base\n";
   print "Result: $result\n";
   
gives

   Base:   http://host/dir1/../dir2/file
   Result: http://host/dir2/file
   
The language in the self test suggests that this is incorrect:

   Similarly, parsers must avoid treating "." and ".." as special when
   they are not complete components of a relative path.

On the other hand, Lynx 2.3.7 and Netscape 1.1N both process .. in relative
URLs that have paths starting with "/".  Lynx does and Netscape does not
process .. in absolute URLs.  (Netscape's *server*, by default, refuses to
acknowledge URLs that come to it with .. and even . segments, on
suspicion that they are trying to climb out of the server's tree.)

Clearly this is not an earthshattering point.  My impulse would be to
say that the law of least surprises suggests leaving .. and .
unprocessed in the base path. In that case the following diff (from the
original 2.9) should do the trick.  I modified the addition to the self
test to cover both things.

-Fritz

*** OLD.URL.pm	Mon Jun  5 10:57:14 1995
--- URL.pm	Mon Jun  5 17:20:04 1995
***************
*** 865,882 ****
  
      $basepath =~ s!^/!!;
      $basepath =~ s!/$!/.!;              # prevent empty segment
!     my @path = split('/', $basepath);   # base path into segments
!     pop(@path);                         # remove last segment
  
      $relpath =~ s!/$!/.!;               # prevent empty segment
  
-     push(@path, split('/', $relpath));  # append relative segments
- 
-     my @newpath = ();
      my $isdir = 0;
      my $segment;
  
!     foreach $segment (@path) {  # left to right
  #       warn '> ', join('/', @newpath), ": $segment\n";
          if ($segment eq '.') {  # ignore "same" directory
              $isdir = 1;
--- 865,879 ----
  
      $basepath =~ s!^/!!;
      $basepath =~ s!/$!/.!;              # prevent empty segment
!     my @newpath = split('/', $basepath);   # base path into segments
!     pop(@newpath);                         # remove last segment
  
      $relpath =~ s!/$!/.!;               # prevent empty segment
  
      my $isdir = 0;
      my $segment;
  
!     foreach $segment (split('/', $relpath)) {  # left to right
  #       warn '> ', join('/', @newpath), ": $segment\n";
          if ($segment eq '.') {  # ignore "same" directory
              $isdir = 1;
***************
*** 901,907 ****
          }
      }
  
!     $embed->{path} = join('/', @newpath) . ($isdir ? '/' : '');
      $embed;
  }
  
--- 898,904 ----
          }
      }
  
!     $embed->{path} = '/' . join('/', @newpath) . ($isdir && @newpath ? '/' : '');
      $embed;
  }
  
***************
*** 1552,1556 ****
--- 1549,1562 ----
          my $got = $u->abs;
          $got->_expect('as_string', $abs_str);
      }
+ 
+     # bug found in 2.9 by "J.E. Fritz" <FRITZ@gems.vcu.edu>
+ 
+     my $base = new URI::URL 'http://host/dir1/../dir2/file';
+     my $relative = new URI::URL 'file', $base;
+     my $result = $relative->abs;
+     my ($a, $b) = ($base->path, $result->path);
+ 	die "'$a' and '$b' should be the same" unless $a eq $b;
+ 
      print "absolute test ok\n";
  }