Stab in the dark

Martin Hamilton (
Thu, 17 Mar 1994 00:24:02 --100

Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
Content-Length: 2111

Hi folks,

The attached code is a very rough sketch of a possible solution to
the URN->UR*->URL scenario which relies on the DNS, HTTP and HTML.
I'm not suggesting this is The Answer as far as URNs are concerned.
An Answer, perhaps? :-)

There is a demo running with the NCSA httpd on

The theory is that the first script is run under the nph- "rule"
by the Web server, which enables it to send re-directs to the
client (your client must support re-directs :-).

In attempting to resolve a URN of the form


it does a DNS TXT lookup on the domain component, e.g. 86400 TXT

Because I'm lazy, the first http URL returned is taken as the URL
of the server which is willing to perform the URN resolution. Then
the rest of the URN is appended - in the example this gives us

In the demo /urn is remapped to the second script via a ScriptAlias

ScriptAlias /urn/ /usr/local/etc/httpd/cgi-bin/stuff/

which does an on-the-fly HTML rendering of an URC template-style
thing, e.g.

Title: Top level "URN"
Description: This is my first attempt to play around with the URN+URC
approach to organizing (meta? ;-)information. It would probably be
better if the URC were interpreted by the client!
Title-v0: MRRL Web server
Title-v1: Hill's Web server
URL-v2: gopher://
Title-v2: Computing Services gopher server

becomes what you see in

Should this idea catch on, I presume most of this code would end up in
the WWW client. Thus, deciding which TXT RR to use, and how the URC
is processed (i.e. more likely as a template/urc than a text/html)
would probably be left up to the client (with hints from the user!).
Adding the client side code (in say Mosaic or Lynx) doesn't look like
it should be a big deal, but I'm sure the client authors will
immediately tell me why it is...



Content-Type: text/plain
Content-Name: nph-urn2urc
Content-Length: 783

#!/usr/local/bin/perl -- #-*-Perl-*-

$dig = "/usr/local/bin/dig";
$default = "";

$urn = $ENV{"QUERY_STRING"};
$urn =~ tr/;\`//;
$urn =~ tr/+/ /;
$urn =~ s/%(..)/pack("c",hex($1))/ge;
$urn =~ s/^urn=//;

($host,$resource) = $urn =~ m!^urn://([^/]+)/(.*)$!;

chop(@DIG = `$dig txt $host +pfset=0x2020`);
next if /^\s+$/;

if (/^$host\.\s+TXT\s+(.*)$/) {
$url = $1;
$url =~ s/;//g;
$url =~ s/\`//g;

if ($url =~ /^http/) { # simple-minded - pick first http !!
print "HTTP/1.0 302 Found\n";
print "Location: $url/$resource\n";
print "Server: $ENV{\"SERVER_SOFTWARE\"}\n";

print "HTTP/1.0 302 Found\n";
print "Location: $default\n";
print "Server: $ENV{\"SERVER_SOFTWARE\"}\n";

Content-Type: text/plain
Content-Name: stuff
Content-Length: 741


($user,$path) = $ENV{"PATH_INFO"} =~ m!^/([^/]+)/(.*)$!;
$top = (getpwnam($user))[7];

print "Content-Type: text/html\n\n<html><head>\n";

open(TOP,"$top/.world/$path")||die "Couldn't open $top/.world/$path: $!";
while(<TOP>) {

if (/^Title:\s*(.*)$/) {
print "<title>$1</title></head><body><h2>Title</h2>$1<p>\n";

if (/^Description:\s*(.*)$/) {
print "<h2>Description</h2>$1\n";

while(<TOP>) {
last unless /^\s/;

print "<p><h2>Links</h2><ul>\n";

if (/^URL-v([^:]+):\s*(.*)$/) {
$urlv = $2;

if (/^Title-v([^:]+):\s*(.*)$/) {
print "<li><a href=\"$urlv\">$2</a>\n";

print "</ul><p></body></html>\n";

Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
Content-Length: 18