The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
# Copyright (C) 1998 Tuomas J. Lukka
# DISTRIBUTED WITH NO WARRANTY, EXPRESS OR IMPLIED.
# See the GNU Library General Public License (file COPYING in the distribution)
# for conditions of use and redistribution.
#
# This file hadles URLs for FreeWRL -
# the idea is to make it possible to do without libwww-perl
# (I don't know if the emulation really works...)
# 

package VRML::URL;
use strict;
use vars qw/$has_lwp/;

# See if we have libwww-perl

unless($VRML::ENV{FREEWRL_NO_LWP})  {

	eval 'require LWP::Simple; require URI::URL;';
	if($@) {
		warn "You don't seem to have libwww-perl installed.
	Cannot get files from the net";
	} else {
		$has_lwp = 1;
	}

}

##############################################################
#
# We make it possible to save stuff 

my %saved;

{
my $ind = 0;


sub save_file {
	my $s;
	if($s = $VRML::ENV{FREEWRL_SAVE}) {
		system("cp $_[1] $s/s$ind");
		system(qq{echo "$_[0] -> $s/s$ind" >>$s/dir});
		$ind ++;
	}
	$saved{"$_[0]:$_[2]"} = $_[1];
	return $_[1];
}

sub save_text {
	my $s;
	if($s = $VRML::ENV{FREEWRL_SAVE}) {
		open FOO, ">$s/s$ind";
		print FOO $_[1];
		close FOO;
		system(qq{echo "$_[0] -> $s/s$ind" >>$s/dir});
		$ind ++;
	}
	$saved{"$_[0]:$_[2]"} = $_[1];
	return $_[1];
}

}

##############################################################
#
# Much of the VRML content is gzipped -- we have to recognize
# it in the run.

sub is_gzip {
	if($_[0] =~ /^\037\213/) {
		warn "GZIPPED content -- trying to ungzip\n";
		return 1;
	}
	return 0;
}

sub ungzip_file {
	my($file) = @_;
	if($file !~ /^[-\w~\.,\/]+$/) {
	 warn("Suspicious file name '$file' -- not gunzipping");
	 return $file;
	}
	open URLFOO,"<$file";
	my $a;
	read URLFOO, $a, 10;
	if(is_gzip($a)) {
		print "Seems to be gzipped - ungzipping\n" if $VRML::verbose::url;
		my $f = temp_file();
		system("gunzip <$file >$f") == 0
		 or die("Gunzip failed: $?");
		return $f;
	} else {
		return $file;
	}
	close URLFOO;
}

sub ungzip_text {
	if(is_gzip($_[0])) {
		my $f = temp_file();
		open URLBAR, "|gunzip >$f";
		local $SIG{PIPE} = sub { die("Gunzip pipe broke"); };
		print URLBAR $_[0];
		close URLBAR || die("bad Gunzip: $! $?");;
		open URLFOO, "<$f";
		my $t = join '',<URLFOO>;
		close URLFOO;
		return $t;
	}
	return $_[0];
}

sub get_really {
	my ($url) = @_;
	$url = URI::URL::url($url,"file:".getcwd()."/")->abs->as_string;
	print "VRML::URI really '$url'\n" if $VRML::verbose::url;
	return $url;
}

sub get_absolute {
	my($url,$as_file) = @_;
	if($saved{"$url:$as_file"}) {
		return $saved{"$url:$as_file"}
	}
	print "VRML::URI::get_absolute('$url', $as_file)\n" if $VRML::verbose::url;
	if($has_lwp) {
		use POSIX qw/getcwd/;
		$url = get_really($url);
		if(!$as_file) {
			my $r = LWP::Simple::get($url);
			if(!defined $r) {die("URL not obtained: '$url'... something is wrong\n")}
			print "VRML::URI: GOT ".length($r)." bytes\n" if $VRML::verbose::url;
			return save_text($url,ungzip_text($r), $as_file);
		} else {
			if($url =~ /^file:(.*)$/) {
				return save_file($url,ungzip_file($1), $as_file);
			} else {
				my($name) = temp_file();
				LWP::Simple::getstore($url,$name);
				return save_file($url,ungzip_file($name), $as_file);
			}
		}
	} else {
		if(-e $url) {
			$url = ungzip_file($url);
			if($as_file) {return save_file($url,$url, $as_file)}
			open FOOFILE, "<$url";
			my $str = join '',<FOOFILE>;
			close FOOFILE;
			return save_text($url,$str, $as_file);
		} else {
			die("Cannot find file '$url' -- if it is a web
address, you need to install libwww-perl \n");
		}
	}
}

sub get_relative {
	my($base,$extra,$as_file) = @_;
	$base = get_really($base);
	print "VRML::URI::get_relative('$base', '$extra', $as_file)\n" if $VRML::verbose::url;
	my $url;
	if($has_lwp) {
		$url = URI::URL::url($extra,$base)->abs->as_string;
	} else {
		$url = $base;
		$url =~ s/[^\/]+$/$extra/ or die("Can't do relativization");
	}
	my $txt = get_absolute($url,$as_file);
	return (wantarray ? ($txt, $url) : $txt);
}

# Taken from perlfaq5
{
my %temps;
BEGIN {
	use IO::File;
	use Fcntl;
	my $temp_dir = -d '/tmp' ? '/tmp' : $ENV{TMP} || $ENV{TEMP};
	my $base_name = sprintf("%s/freewrl-%d-%d-00000", $temp_dir, $$, time());
	sub temp_file {
	   my $fh = undef;
	   my $count = 0;
	   until (defined($fh) || $count > 100) {
	       $base_name =~ s/-(\d+)$/"-" . (1 + $1)/e;
	       $temps{$base_name} = 1;
	       $fh = IO::File->new($base_name, O_WRONLY|O_EXCL|O_CREAT,0644)
	   }
	   if (defined($fh)) {
	       undef $fh;
	       unlink $base_name;
	       return $base_name;
	   } else {
	       die("Couldn't make temp file");
	   }
	}
}
sub unlinktmp {
	if(!$temps{$_[0]}) {
		die("Trying to unlink nonexistent tmp");
	}
	unlink $_[0];
	delete $temps{$_[0]};
}
END {
	for(keys %temps) {
		print "unlinking '$_' (NOT)\n" if $VRML::verbose::url;
		# unlink $_;
	}
}
}

1;