--- loncom/lonnet/perl/lonnet.pm	2004/01/26 21:58:34	1.464
+++ loncom/lonnet/perl/lonnet.pm	2004/03/19 16:45:25	1.479
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # TCP networking package
 #
-# $Id: lonnet.pm,v 1.464 2004/01/26 21:58:34 albertel Exp $
+# $Id: lonnet.pm,v 1.479 2004/03/19 16:45:25 albertel Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -377,7 +377,12 @@ sub delenv {
 	    return 'error: '.$!;
 	}
 	foreach (@oldenv) {
-	    unless ($_=~/^$delthis/) { print $fh $_; }
+	    if ($_=~/^$delthis/) { 
+                my ($key,undef) = split('=',$_);
+                delete($ENV{$key});
+            } else {
+                print $fh $_; 
+            }
 	}
 	close($fh);
     }
@@ -524,38 +529,21 @@ sub authenticate {
     my ($uname,$upass,$udom)=@_;
     $upass=escape($upass);
     $uname=~s/\W//g;
-    if (($perlvar{'lonRole'} eq 'library') && 
-        ($udom eq $perlvar{'lonDefDomain'})) {
-    my $answer=reply("encrypt:auth:$udom:$uname:$upass",$perlvar{'lonHostID'});
-        if ($answer =~ /authorized/) {
-              if ($answer eq 'authorized') {
-                 &logthis("User $uname at $udom authorized by local server"); 
-                 return $perlvar{'lonHostID'}; 
-              }
-              if ($answer eq 'non_authorized') {
-                 &logthis("User $uname at $udom rejected by local server"); 
-                 return 'no_host'; 
-              }
-	}
+    my $uhome=&homeserver($uname,$udom);
+    if (!$uhome) {
+	&logthis("User $uname at $udom is unknown in authenticate");
+	return 'no_host';
     }
-
-    my $tryserver;
-    foreach $tryserver (keys %libserv) {
-	if ($hostdom{$tryserver} eq $udom) {
-           my $answer=reply("encrypt:auth:$udom:$uname:$upass",$tryserver);
-           if ($answer =~ /authorized/) {
-              if ($answer eq 'authorized') {
-                 &logthis("User $uname at $udom authorized by $tryserver"); 
-                 return $tryserver; 
-              }
-              if ($answer eq 'non_authorized') {
-                 &logthis("User $uname at $udom rejected by $tryserver");
-                 return 'no_host';
-              } 
-	   }
-       }
+    my $answer=reply("encrypt:auth:$udom:$uname:$upass",$uhome);
+    if ($answer eq 'authorized') {
+	&logthis("User $uname at $udom authorized by $uhome"); 
+	return $uhome; 
+    }
+    if ($answer eq 'non_authorized') {
+	&logthis("User $uname at $udom rejected by $uhome");
+	return 'no_host'; 
     }
-    &logthis("User $uname at $udom could not be authenticated");    
+    &logthis("User $uname at $udom threw error $answer when checking authentication mechanism");
     return 'no_host';
 }
 
@@ -661,7 +649,7 @@ sub assign_access_key {
     $uname=$ENV{'user.domain'} unless (defined($uname));
     my %existing=&get('accesskeys',[$ckey],$cdom,$cnum);
     if (($existing{$ckey}=~/^\#(.*)$/) || # - new key
-        ($existing{$ckey}=~/^$uname\:$udom\#(.*)$/)) { 
+        ($existing{$ckey}=~/^\Q$uname\E\:\Q$udom\E\#(.*)$/)) { 
                                                   # assigned to this person
                                                   # - this should not happen,
                                                   # unless something went wrong
@@ -768,7 +756,7 @@ sub validate_access_key {
     $udom=$ENV{'user.name'} unless (defined($udom));
     $uname=$ENV{'user.domain'} unless (defined($uname));
     my %existing=&get('accesskeys',[$ckey],$cdom,$cnum);
-    return ($existing{$ckey}=~/^$uname\:$udom\#/);
+    return ($existing{$ckey}=~/^\Q$uname\E\:\Q$udom\E\#/);
 }
 
 # ------------------------------------- Find the section of student in a course
@@ -796,7 +784,7 @@ sub getsection {
                         &homeserver($unam,$udom)))) {
         my ($key,$value)=split(/\=/,$_);
         $key=&unescape($key);
-        next if ($key !~/^$courseid(?:\/)*(\w+)*\_st$/);
+        next if ($key !~/^\Q$courseid\E(?:\/)*(\w+)*\_st$/);
         my $section=$1;
         if ($key eq $courseid.'_st') { $section=''; }
         my ($dummy,$end,$start)=split(/\_/,&unescape($value));
@@ -975,7 +963,7 @@ sub usection {
                         &homeserver($unam,$udom)))) {
         my ($key,$value)=split(/\=/,$_);
         $key=&unescape($key);
-        if ($key=~/^$courseid(?:\/)*(\w+)*\_st$/) {
+        if ($key=~/^\Q$courseid\E(?:\/)*(\w+)*\_st$/) {
             my $section=$1;
             if ($key eq $courseid.'_st') { $section=''; }
 	    my ($dummy,$end,$start)=split(/\_/,&unescape($value));
@@ -1183,7 +1171,8 @@ sub tokenwrapper {
     $uri=~s/^\///;
     $ENV{'user.environment'}=~/\/([^\/]+)\.id/;
     my $token=$1;
-    if ($uri=~/^uploaded\/([^\/]+)\/([^\/]+)\/([^\/]+)(\?\.*)*$/) {
+#    if ($uri=~/^uploaded\/([^\/]+)\/([^\/]+)\/([^\/]+)(\?\.*)*$/) {
+    if ($uri=~m|^uploaded/([^/]+)/([^/]+)/(.+)(\?\.*)*$|) {
 	&appenv('userfile.'.$1.'/'.$2.'/'.$3 => $ENV{'request.course.id'});
         return 'http://'.$hostname{ &homeserver($2,$1)}.'/'.$uri.
                (($uri=~/\?/)?'&':'?').'token='.$token.
@@ -1192,7 +1181,65 @@ sub tokenwrapper {
 	return '/adm/notfound.html';
     }
 }
-    
+
+# --------- File operations in /home/httpd/html/userfiles/$domain/1/2/3/$course
+# input: action, courseID, current domain, home server for course, intended
+#        path to file, source of file.
+# output: ok if successful, diagnostic message otherwise
+#
+# Allows directory structure to be used within lonUsers/../userfiles/ for a 
+# course.
+#
+# action = propagate - /home/httpd/html/userfiles/$domain/1/2/3/$course/$file
+#          will be copied to /home/httpd/lonUsers/1/2/3/$course/userfiles in
+#          course's home server.
+#
+# action = copy - /home/httpd/html/userfiles/$domain/1/2/3/$course/$file will
+#          be copied from $source (current location) to 
+#          /home/httpd/html/userfiles/$domain/1/2/3/$course/$file
+#         and will then be copied to
+#          /home/httpd/lonUsers/$domain/1/2/3/$course/userfiles/$file in
+#         course's home server.
+
+sub process_coursefile {
+    my ($action,$docuname,$docudom,$docuhome,$file,$source)=@_;
+    my $fetchresult;
+    if ($action eq 'propagate') {
+        $fetchresult= &reply('fetchuserfile:'.$docudom.'/'.$docuname.'/'.$file
+                            ,$docuhome);
+    } elsif ($action eq 'copy') {
+        my $fetchresult = '';
+        my $fpath = '';
+        my $fname = $file;
+        ($fpath,$fname) = ($file =~ m|^(.*)/([^/]+)$|);
+        $fpath=$docudom.'/'.$docuname.'/'.$fpath;
+        my $filepath=$perlvar{'lonDocRoot'}.'/userfiles';
+        unless ($fpath eq '') {
+            my @parts=split('/',$fpath);
+            foreach my $part (@parts) {
+                $filepath.= '/'.$part;
+                if ((-e $filepath)!=1) {
+                    mkdir($filepath,0777);
+                }
+            }
+        }
+        if ($source eq '') {
+            $fetchresult = 'no source file';
+        } else {
+            my $destination = $filepath.'/'.$fname;
+            print STDERR "Getting ready to rename $source to $destination\n";
+            rename($source,$destination);
+            $fetchresult= &reply('fetchuserfile:'.$docudom.'/'.$docuname.'/'.$file,
+                                 $docuhome);
+        }
+    }
+    unless ( ($fetchresult eq 'ok') || ($fetchresult eq 'no source file') ) {
+        &logthis('Failed to transfer '.$docudom.'/'.$docuname.'/'.$file.
+             ' to host '.$docuhome.': '.$fetchresult);
+    }
+    return $fetchresult;
+}
+
 # --------------- Take an uploaded file and put it into the userfiles directory
 # input: name of form element, coursedoc=1 means this is for the course
 # output: url of file in userspace
@@ -1248,9 +1295,8 @@ sub finishuserfileupload {
     }
 # Notify homeserver to grep it
 #
-    
-    my $fetchresult= 
- &reply('fetchuserfile:'.$docudom.'/'.$docuname.'/'.$fname,$docuhome);
+    my $fetchresult= &reply('fetchuserfile:'.$docudom.'/'.$docuname.'/'.$fname,
+			    $docuhome);
     if ($fetchresult eq 'ok') {
 #
 # Return the URL to it
@@ -1424,7 +1470,7 @@ sub userrolelog {
     my ($trole,$username,$domain,$area,$tstart,$tend)=@_;
     if (($trole=~/^ca/) || ($trole=~/^in/) || 
         ($trole=~/^cc/) || ($trole=~/^ep/) ||
-        ($trole=~/^cr/)) {
+        ($trole=~/^cr/) || ($trole=~/^ta/)) {
        my (undef,$rudom,$runame,$rsec)=split(/\//,$area);
        $userrolehash
          {$trole.':'.$username.':'.$domain.':'.$runame.':'.$rudom.':'.$rsec}
@@ -1436,6 +1482,10 @@ sub get_course_adv_roles {
     my $cid=shift;
     $cid=$ENV{'request.course.id'} unless (defined($cid));
     my %coursehash=&coursedescription($cid);
+    my %nothide=();
+    foreach (split(/\s*\,\s*/,$coursehash{'nothideprivileged'})) {
+	$nothide{join(':',split(/[\@\:]/,$_))}=1;
+    }
     my %returnhash=();
     my %dumphash=
             &dump('nohist_userroles',$coursehash{'domain'},$coursehash{'num'});
@@ -1446,6 +1496,8 @@ sub get_course_adv_roles {
         if (($tend) && ($tend<$now)) { next; }
         if (($tstart) && ($now<$tstart)) { next; }
         my ($role,$username,$domain,$section)=split(/\:/,$_);
+	if ((&privileged($username,$domain)) && 
+	    (!$nothide{$username.':'.$domain})) { next; }
         my $key=&plaintext($role);
         if ($section) { $key.=' (Sec/Grp '.$section.')'; }
         if ($returnhash{$key}) {
@@ -2577,14 +2629,14 @@ sub allowed {
 
 # Course
 
-    if ($ENV{'user.priv.'.$ENV{'request.role'}.'./'}=~/$priv\&([^\:]*)/) {
+    if ($ENV{'user.priv.'.$ENV{'request.role'}.'./'}=~/\Q$priv\E\&([^\:]*)/) {
        $thisallowed.=$1;
     }
 
 # Domain
 
     if ($ENV{'user.priv.'.$ENV{'request.role'}.'./'.(split(/\//,$uri))[0].'/'}
-       =~/$priv\&([^\:]*)/) {
+       =~/\Q$priv\E\&([^\:]*)/) {
        $thisallowed.=$1;
     }
 
@@ -2594,7 +2646,7 @@ sub allowed {
     $courseuri=~s/^([^\/])/\/$1/;
 
     if ($ENV{'user.priv.'.$ENV{'request.role'}.'.'.$courseuri}
-       =~/$priv\&([^\:]*)/) {
+       =~/\Q$priv\E\&([^\:]*)/) {
        $thisallowed.=$1;
     }
 
@@ -2612,7 +2664,7 @@ sub allowed {
 
 # If this is generating or modifying users, exit with special codes
 
-    if (':csu:cdc:ccc:cin:cta:cep:ccr:cst:cad:cli:cau:cdg:cca:'=~/\:$priv\:/) {
+    if (':csu:cdc:ccc:cin:cta:cep:ccr:cst:cad:cli:cau:cdg:cca:'=~/\:\Q$priv\E\:/) {
 	return $thisallowed;
     }
 #
@@ -2633,7 +2685,7 @@ sub allowed {
        if ($match) {
            $statecond=$cond;
            if ($ENV{'user.priv.'.$ENV{'request.role'}.'./'.$courseprivid}
-               =~/$priv\&([^\:]*)/) {
+               =~/\Q$priv\E\&([^\:]*)/) {
                $thisallowed.=$1;
                $checkreferer=0;
            }
@@ -2661,7 +2713,7 @@ sub allowed {
             if ($match) {
               my $refstatecond=$cond;
               if ($ENV{'user.priv.'.$ENV{'request.role'}.'./'.$courseprivid}
-                  =~/$priv\&([^\:]*)/) {
+                  =~/\Q$priv\E\&([^\:]*)/) {
                   $thisallowed.=$1;
                   $uri=$refuri;
                   $statecond=$refstatecond;
@@ -2714,7 +2766,7 @@ sub allowed {
                if ((time-$ENV{$prefix.'last_cache'})>$expiretime) {
 		   &coursedescription($courseid);
                }
-               if (($ENV{$prefix.'res.'.$uri.'.lock.sections'}=~/\,$csec\,/)
+               if (($ENV{$prefix.'res.'.$uri.'.lock.sections'}=~/\,\Q$csec\E\,/)
                 || ($ENV{$prefix.'res.'.$uri.'.lock.sections'} eq 'all')) {
 		   if ($ENV{$prefix.'res.'.$uri.'.lock.expire'}>time) {
                        &log($ENV{'user.domain'},$ENV{'user.name'},
@@ -2725,7 +2777,7 @@ sub allowed {
 		       return '';
                    }
                }
-               if (($ENV{$prefix.'priv.'.$priv.'.lock.sections'}=~/\,$csec\,/)
+               if (($ENV{$prefix.'priv.'.$priv.'.lock.sections'}=~/\,\Q$csec\E\,/)
                 || ($ENV{$prefix.'priv.'.$priv.'.lock.sections'} eq 'all')) {
 		   if ($ENV{'priv.'.$priv.'.lock.expire'}>time) {
                        &log($ENV{'user.domain'},$ENV{'user.name'},
@@ -2759,7 +2811,7 @@ sub allowed {
        my $rolecode=(split(/\./,$ENV{'request.role'}))[0];
        my $unamedom=$ENV{'user.name'}.':'.$ENV{'user.domain'};
        if ($ENV{'course.'.$ENV{'request.course.id'}.'.'.$priv.'.roles.denied'}
-	   =~/$rolecode/) {
+	   =~/\Q$rolecode\E/) {
            &log($ENV{'user.domain'},$ENV{'user.name'},$ENV{'user.host'},
                 'Denied by role: '.$priv.' for '.$uri.' as '.$rolecode.' in '.
                 $ENV{'request.course.id'});
@@ -2767,7 +2819,7 @@ sub allowed {
        }
 
        if ($ENV{'course.'.$ENV{'request.course.id'}.'.'.$priv.'.users.denied'}
-	   =~/$unamedom/) {
+	   =~/\Q$unamedom\E/) {
            &log($ENV{'user.domain'},$ENV{'user.name'},$ENV{'user.host'},
                 'Denied by user: '.$priv.' for '.$uri.' as '.$unamedom.' in '.
                 $ENV{'request.course.id'});
@@ -2779,7 +2831,7 @@ sub allowed {
 
    if ($thisallowed=~/R/) {
        my $rolecode=(split(/\./,$ENV{'request.role'}))[0];
-       if (&metadata($uri,'roledeny')=~/$rolecode/) {
+       if (&metadata($uri,'roledeny')=~/\Q$rolecode\E/) {
 	  &log($ENV{'user.domain'},$ENV{'user.name'},$ENV{'user.host'},
                     'Denied by role: '.$priv.' for '.$uri.' as '.$rolecode);
           return '';
@@ -2791,7 +2843,7 @@ sub allowed {
    if ($thisallowed=~/X/) {
       if ($ENV{'acc.randomout'}) {
          my $symb=&symbread($uri,1);
-         if (($symb) && ($ENV{'acc.randomout'}=~/\&$symb\&/)) { 
+         if (($symb) && ($ENV{'acc.randomout'}=~/\&\Q$symb\E\&/)) { 
             return ''; 
          }
       }
@@ -2855,27 +2907,27 @@ sub definerole {
     my ($rolename,$sysrole,$domrole,$courole)=@_;
     foreach (split(':',$sysrole)) {
 	my ($crole,$cqual)=split(/\&/,$_);
-        if ($pr{'cr:s'}!~/$crole/) { return "refused:s:$crole"; }
-        if ($pr{'cr:s'}=~/$crole\&/) {
-	    if ($pr{'cr:s'}!~/$crole\&\w*$cqual/) { 
+        if ($pr{'cr:s'}!~/\Q$crole\E/) { return "refused:s:$crole"; }
+        if ($pr{'cr:s'}=~/\Q$crole\E\&/) {
+	    if ($pr{'cr:s'}!~/\Q$crole\E\&\w*\Q$cqual\E/) { 
                return "refused:s:$crole&$cqual"; 
             }
         }
     }
     foreach (split(':',$domrole)) {
 	my ($crole,$cqual)=split(/\&/,$_);
-        if ($pr{'cr:d'}!~/$crole/) { return "refused:d:$crole"; }
-        if ($pr{'cr:d'}=~/$crole\&/) {
-	    if ($pr{'cr:d'}!~/$crole\&\w*$cqual/) { 
+        if ($pr{'cr:d'}!~/\Q$crole\E/) { return "refused:d:$crole"; }
+        if ($pr{'cr:d'}=~/\Q$crole\E\&/) {
+	    if ($pr{'cr:d'}!~/\Q$crole\W\&\w*\Q$cqual\E/) { 
                return "refused:d:$crole&$cqual"; 
             }
         }
     }
     foreach (split(':',$courole)) {
 	my ($crole,$cqual)=split(/\&/,$_);
-        if ($pr{'cr:c'}!~/$crole/) { return "refused:c:$crole"; }
-        if ($pr{'cr:c'}=~/$crole\&/) {
-	    if ($pr{'cr:c'}!~/$crole\&\w*$cqual/) { 
+        if ($pr{'cr:c'}!~/\Q$crole\E/) { return "refused:c:$crole"; }
+        if ($pr{'cr:c'}=~/\Q$crole\E\&/) {
+	    if ($pr{'cr:c'}!~/\Q$crole\E\&\w*\Q$cqual\E/) { 
                return "refused:c:$crole&$cqual"; 
             }
         }
@@ -2922,7 +2974,7 @@ sub log_query {
     my $command=&escape(join(':',map{$_.'='.$filters{$_}} keys %filters));
     my $queryid=&reply("querysend:".$query.':'.$udom.':'.$uname.':'.$command,
                        $uhome);
-    unless ($queryid=~/^$uhost\_/) { return 'error: '.$queryid; }
+    unless ($queryid=~/^\Q$uhost\E\_/) { return 'error: '.$queryid; }
     return get_query_reply($queryid);
 }
 
@@ -3821,10 +3873,11 @@ sub packages_tab_default {
     my $packages=&metadata($uri,'packages');
     foreach my $package (split(/,/,$packages)) {
 	my ($pack_type,$pack_part)=split(/_/,$package,2);
-	if ($pack_part eq $part) {
-	    if (defined($packagetab{"$pack_type&$name&default"})) {
-		return $packagetab{"$pack_type&$name&default"};
-	    }
+	if (defined($packagetab{"$pack_type&$name&default"})) {
+	    return $packagetab{"$pack_type&$name&default"};
+	}
+	if (defined($packagetab{$pack_type."_".$pack_part."&$name&default"})) {
+	    return $packagetab{$pack_type."_".$pack_part."&$name&default"};
 	}
     }
     return undef;
@@ -3854,8 +3907,8 @@ sub metadata {
     # if it is a non metadata possible uri return quickly
     if (($uri eq '') || (($uri =~ m|^/*adm/|) && ($uri !~ m|^adm/includes|)) ||
         ($uri =~ m|/$|) || ($uri =~ m|/.meta$|) || ($uri =~ /^~/) ||
-	($uri =~ m|home/[^/]+/public_html/|)) {
-	return '';
+	($uri =~ m|home/[^/]+/public_html/|) || ($uri =~ m|^uploaded/|)) {
+	return undef;
     }
     my $filename=$uri;
     $uri=~s/\.meta$//;
@@ -4045,7 +4098,7 @@ sub metadata_generate_part0 {
       my $olddis=$$metacache{':parameter_'.$allnames{$name}.'_'.$name.
 			     '.display'};
       my $expr='\\[Part: '.$allnames{$name}.'\\]';
-      $olddis=~s/$expr/\[Part: 0\]/;
+      $olddis=~s/\Q$expr\E/\[Part: 0\]/;
       $$metacache{"$key.display"}=$olddis;
     }
 }
@@ -4403,49 +4456,83 @@ sub setup_random_from_rndseed {
     }
 }
 
+sub latest_receipt_algorithm_id {
+    return 'receipt2';
+}
+
 sub ireceipt {
-    my ($funame,$fudom,$fucourseid,$fusymb)=@_;
+    my ($funame,$fudom,$fucourseid,$fusymb,$part)=@_;
     my $cuname=unpack("%32C*",$funame);
     my $cudom=unpack("%32C*",$fudom);
     my $cucourseid=unpack("%32C*",$fucourseid);
     my $cusymb=unpack("%32C*",$fusymb);
     my $cunique=unpack("%32C*",$perlvar{'lonReceipt'});
-    return unpack("%32C*",$perlvar{'lonHostID'}).'-'.
-           ($cunique%$cuname+
-            $cunique%$cudom+
-            $cusymb%$cuname+
-            $cusymb%$cudom+
-            $cucourseid%$cuname+
-            $cucourseid%$cudom);
+    my $cpart=unpack("%32S*",$part);
+    my $return =unpack("%32C*",$perlvar{'lonHostID'}).'-';
+    if ($ENV{"course.$fucourseid.receiptalg"} eq 'receipt2' ||
+	$ENV{'request.state'} eq 'construct') {
+	&Apache::lonxml::debug("doing receipt2  using parts $cpart, uname $cuname and udom $cudom gets  ".($cpart%$cuname).
+			       " and ".($cpart%$cudom));
+			       
+	$return.= ($cunique%$cuname+
+		   $cunique%$cudom+
+		   $cusymb%$cuname+
+		   $cusymb%$cudom+
+		   $cucourseid%$cuname+
+		   $cucourseid%$cudom+
+		   $cpart%$cuname+
+		   $cpart%$cudom);
+    } else {
+	$return.= ($cunique%$cuname+
+		   $cunique%$cudom+
+		   $cusymb%$cuname+
+		   $cusymb%$cudom+
+		   $cucourseid%$cuname+
+		   $cucourseid%$cudom);
+    }
+    return $return;
 }
 
 sub receipt {
-  my ($symb,$courseid,$domain,$name) = &Apache::lonxml::whichuser();
-  return &ireceipt($name,$domain,$courseid,$symb);
+    my ($part)=@_;
+    my ($symb,$courseid,$domain,$name) = &Apache::lonxml::whichuser();
+    return &ireceipt($name,$domain,$courseid,$symb,$part);
 }
 
 # ------------------------------------------------------------ Serves up a file
-# returns either the contents of the file or a -1
+# returns either the contents of the file or 
+# -1 if the file doesn't exist
+# -2 if an error occured when trying to aqcuire the file
+
 sub getfile {
- my $file=shift;
- if ($file=~/^\/*uploaded\//) { # user file
-    my $ua=new LWP::UserAgent;
-    my $request=new HTTP::Request('GET',&tokenwrapper($file));
-    my $response=$ua->request($request);
-    if ($response->is_success()) {
-       return $response->content;
-    } else { 
-       return -1; 
-    }
- } else { # normal file from res space
-  &repcopy($file);
-  if (! -e $file ) { return -1; };
-  my $fh;
-  open($fh,"<$file");
-  my $a='';
-  while (<$fh>) { $a .=$_; }
-  return $a;
- }
+    my $file=shift;
+    if ($file=~/^\/*uploaded\//) { # user file
+	my $ua=new LWP::UserAgent;
+	my $request=new HTTP::Request('GET',&tokenwrapper($file));
+	my $response=$ua->request($request);
+	if ($response->is_success()) {
+	    return $response->content;
+	} else { 
+	    #&logthis("Return Code is ".$response->code." for $file ".
+	    #         &tokenwrapper($file));
+	    # 500 for ISE when tokenwrapper can't figure out what server to
+            #  contact
+            # 503 when lonuploadacc can't contact the requested server
+	    if ($response->code eq 503 || $response->code eq 500) {
+		return -2;
+	    } else {
+		return -1;
+	    }
+	}
+    } else { # normal file from res space
+	&repcopy($file);
+	if (! -e $file ) { return -1; };
+	my $fh;
+	open($fh,"<$file");
+	my $a='';
+	while (<$fh>) { $a .=$_; }
+	return $a;
+    }
 }
 
 sub filelocation {
@@ -4458,7 +4545,7 @@ sub filelocation {
   } elsif ($file=~/^\/*uploaded/) { # is an uploaded file
     $location=$file;
   } else {
-    $file=~s/^$perlvar{'lonDocRoot'}//;
+    $file=~s/^\Q$perlvar{'lonDocRoot'}\E//;
     $file=~s:^/res/:/:;
     if ( !( $file =~ m:^/:) ) {
       $location = $dir. '/'.$file;
@@ -4468,6 +4555,7 @@ sub filelocation {
   }
   $location=~s://+:/:g; # remove duplicate /
   while ($location=~m:/\.\./:) {$location=~ s:/[^/]+/\.\./:/:g;} #remove dir/..
+  while ($location=~m:/\./:) {$location=~ s:/\./:/:g;} #remove /./
   return $location;
 }
 
@@ -4486,11 +4574,35 @@ sub hreflocation {
     return $file;
 }
 
+sub current_machine_domains {
+    my $hostname=$hostname{$perlvar{'lonHostID'}};
+    my @domains;
+    while( my($id, $name) = each(%hostname)) {
+#	&logthis("-$id-$name-$hostname-");
+	if ($hostname eq $name) {
+	    push(@domains,$hostdom{$id});
+	}
+    }
+    return @domains;
+}
+
+sub current_machine_ids {
+    my $hostname=$hostname{$perlvar{'lonHostID'}};
+    my @ids;
+    while( my($id, $name) = each(%hostname)) {
+#	&logthis("-$id-$name-$hostname-");
+	if ($hostname eq $name) {
+	    push(@ids,$id);
+	}
+    }
+    return @ids;
+}
+
 # ------------------------------------------------------------- Declutters URLs
 
 sub declutter {
     my $thisfn=shift;
-    $thisfn=~s/^$perlvar{'lonDocRoot'}//;
+    $thisfn=~s/^\Q$perlvar{'lonDocRoot'}\E//;
     $thisfn=~s/^\///;
     $thisfn=~s/^res\///;
     $thisfn=~s/\?.+$//;