--- loncom/lonenc.pm	2006/04/07 22:15:34	1.14
+++ loncom/lonenc.pm	2011/09/30 15:58:05	1.25
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # URL translation for encrypted filenames
 #
-# $Id: lonenc.pm,v 1.14 2006/04/07 22:15:34 albertel Exp $
+# $Id: lonenc.pm,v 1.25 2011/09/30 15:58:05 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -32,24 +32,56 @@ use strict;
 use Apache::lonnet;
 use Crypt::IDEA;
 use Time::HiRes qw(gettimeofday);
+use LONCAPA;
+ 
+
+#
+#  If a module makes multiple SSI calls and some of the ssi calls result in a
+#  resource for an encoded URL, and this can be done in an unprivileged role,
+#  there must be a mechanism t oreset the 'request.enc' environment variable.
+#  This sub centralizes that mechanism:
+#
+sub reset_enc {
+    $env{'request.enc'} = 0;
+}
 
 sub encryptseed {
-    my $seed=$env{'course.'.$env{'request.course.id'}.'.internal.encseed'};
-    $seed=~s/[^0-9a-f]/0/g;
-    $seed.='0123456789abcdef';
-    $seed=substr($seed.$seed,0,32);
-    return pack("H32",$seed);
+    my ($cid) = @_;
+    if (!defined($cid)) {
+        $cid = $env{'request.course.id'};
+    }
+    my $seed;
+    if (defined($cid)) {
+        if (defined$env{'course.'.$cid.'.internal.encseed'}) {
+            $seed = $env{'course.'.$cid.'.internal.encseed'};
+        } else {
+            my %descargs = ( 'one_time' => 1);
+            my %course = 
+               &Apache::lonnet::coursedescription($cid,\%descargs);
+            $seed = $course{'internal.encseed'};
+        }
+    }
+    if (defined($seed)) {
+        $seed=~s/[^0-9a-f]/0/g;
+        $seed.='0123456789abcdef';
+        $seed=substr($seed.$seed,0,32);
+        return pack("H32",$seed);
+    } else {
+        return pack("H32",1);
+    }
 }
 
 sub unencrypted {
-    my $uri=shift;
+    my ($uri,$cid) = @_;
     $uri=~s/^\/enc\/(\d+)\///;
     my $cmdlength=$1;
-    my $seed=&encryptseed();
+    # strip any added extension
+    $uri=~s/\.[^.]*//;
+    my $seed=&encryptseed($cid);
     unless ($seed) {
 	return '/'.$uri;
     }
-    $uri=&Apache::lonnet::unescape($uri);
+    $uri=&unescape($uri);
     my $cipher=new IDEA $seed;
     my $decuri='';
     for (my $encidx=0;$encidx<length($uri);$encidx+=16) {
@@ -101,12 +133,17 @@ sub encrypted {
 	$encuri.=unpack("H16",
 			$cipher->encrypt(substr($uri,$encidx,8)));
     }
-    return '/enc/'.$cmdlength.'/'.&Apache::lonnet::escape($encuri);
+    return '/enc/'.$cmdlength.'/'.&escape($encuri);
 }
 
 sub check_encrypt {
     my $str=shift;
-    if ($env{'request.enc'}) { return &Apache::lonenc::encrypted($str); }
+    if (ref($str)) {
+        if ($env{'request.enc'}) { $$str = &Apache::lonenc::encrypted($$str); }
+        return;
+    } else {
+        if ($env{'request.enc'}) { return &Apache::lonenc::encrypted($str); }
+    }
     return $str;
 }
 
@@ -125,10 +162,16 @@ sub encrypt_ref {
     my $html;
     if ($force_enc || $env{'request.enc'}) {
 	while (my ($name,$value)= each(%{ $elements })) {
-	    if (!$value) { next; }
+	    next if (!$value); 
+	    next if ($value =~ /^\w+:/); # explict javascript: or http: link
 	    my $href=&Apache::lonnet::hreflocation($Apache::lonxml::pwd[-1],$value);
-	    if ($href !~ /^http:/) {
-		$href = &Apache::lonenc::encrypted($href,$force_enc);
+	    if ($href !~ /^https?\:/) {
+		# IE really wants an extension
+		my ($extension) = ($href =~ m/(\.[^.]*)$/);
+		my $newhref = &Apache::lonenc::encrypted($href,$force_enc);
+		unless ($newhref eq $href) {
+		    $href = $newhref.$extension;
+		}
 	    }
 	    $token->[2]->{$name}=$href;
 	}