Diff for /loncom/lonnet/perl/lonnet.pm between versions 1.990 and 1.1056.2.10

version 1.990, 2009/03/09 05:25:44 version 1.1056.2.10, 2010/11/11 21:01:38
Line 74  use strict; Line 74  use strict;
 use LWP::UserAgent();  use LWP::UserAgent();
 use HTTP::Date;  use HTTP::Date;
 use Image::Magick;  use Image::Magick;
 use IO::Socket;  
   
 # use Date::Parse;  
 use vars qw(%perlvar %spareid %pr %prp $memcache %packagetab $tmpdir  use vars qw(%perlvar %spareid %pr %prp $memcache %packagetab $tmpdir
             $_64bit %env %protocol);              $_64bit %env %protocol);
   
Line 94  use Time::HiRes qw( gettimeofday tv_inte Line 92  use Time::HiRes qw( gettimeofday tv_inte
 use Cache::Memcached;  use Cache::Memcached;
 use Digest::MD5;  use Digest::MD5;
 use Math::Random;  use Math::Random;
   use File::MMagic;
 use LONCAPA qw(:DEFAULT :match);  use LONCAPA qw(:DEFAULT :match);
 use LONCAPA::Configuration;  use LONCAPA::Configuration;
   
 my $readit;  my $readit;
 my $max_connection_retries = 10;     # Or some such value.  my $max_connection_retries = 10;     # Or some such value.
   
 my $upload_photo_form = 0; #Variable to check  when user upload a photo 0=not 1=true  
   
 require Exporter;  require Exporter;
   
 our @ISA = qw (Exporter);  our @ISA = qw (Exporter);
Line 198  sub get_server_timezone { Line 195  sub get_server_timezone {
     }      }
 }  }
   
   sub get_server_loncaparev {
       my ($dom,$lonhost) = @_;
       if (defined($lonhost)) {
           if (!defined(&hostname($lonhost))) {
               undef($lonhost);
           }
       }
       if (!defined($lonhost)) {
           if (defined(&domain($dom,'primary'))) {
               $lonhost=&domain($dom,'primary');
               if ($lonhost eq 'no_host') {
                   undef($lonhost);
               }
           }
       }
       if (defined($lonhost)) {
           my $cachetime = 24*3600;
           my ($loncaparev,$cached)=&is_cached_new('serverloncaparev',$lonhost);
           if (defined($cached)) {
               return $loncaparev;
           } else {
               my $loncaparev = &reply('serverloncaparev',$lonhost);
               return &do_cache_new('serverloncaparev',$lonhost,$loncaparev,$cachetime);
           }
       }
   }
   
 # -------------------------------------------------- Non-critical communication  # -------------------------------------------------- Non-critical communication
 sub subreply {  sub subreply {
     my ($cmd,$server)=@_;      my ($cmd,$server)=@_;
Line 693  sub spareserver { Line 717  sub spareserver {
         if ($protocol{$spare_server} eq 'https') {          if ($protocol{$spare_server} eq 'https') {
             $protocol = $protocol{$spare_server};              $protocol = $protocol{$spare_server};
         }          }
  $spare_server = $protocol.'://'.&hostname($spare_server);          if (defined($spare_server)) {
               my $hostname = &hostname($spare_server);
               if (defined($hostname)) {  
           $spare_server = $protocol.'://'.$hostname;
               }
           }
     }      }
     return $spare_server;      return $spare_server;
 }  }
Line 754  sub changepass { Line 783  sub changepass {
     my ($uname,$udom,$currentpass,$newpass,$server,$context)=@_;      my ($uname,$udom,$currentpass,$newpass,$server,$context)=@_;
     $currentpass = &escape($currentpass);      $currentpass = &escape($currentpass);
     $newpass     = &escape($newpass);      $newpass     = &escape($newpass);
     my $answer = reply("encrypt:passwd:$udom:$uname:$currentpass:$newpass:$context",      my $lonhost = $perlvar{'lonHostID'};
       my $answer = reply("encrypt:passwd:$udom:$uname:$currentpass:$newpass:$context:$lonhost",
        $server);         $server);
     if (! $answer) {      if (! $answer) {
  &logthis("No reply on password change request to $server ".   &logthis("No reply on password change request to $server ".
Line 779  sub changepass { Line 809  sub changepass {
     } elsif ($answer =~ "^refused") {      } elsif ($answer =~ "^refused") {
  &logthis("$server refused to change $uname in $udom password because ".   &logthis("$server refused to change $uname in $udom password because ".
  "it was sent an unencrypted request to change the password.");   "it was sent an unencrypted request to change the password.");
       } elsif ($answer =~ "invalid_client") {
           &logthis("$server refused to change $uname in $udom password because ".
                    "it was a reset by e-mail originating from an invalid server.");
     }      }
     return $answer;      return $answer;
 }  }
Line 928  sub idput { Line 961  sub idput {
     }      }
 }  }
   
 # ------------------------------------------- get items from domain db files     # ------------------------------dump from db file owned by domainconfig user
   sub dump_dom {
       my ($namespace,$udom,$regexp,$range)=@_;
       if (!$udom) {
           $udom=$env{'user.domain'};
       }
       my %returnhash;
       if ($udom) {
           my $uname = &get_domainconfiguser($udom);
           %returnhash = &dump($namespace,$udom,$uname,$regexp,$range);
       }
       return %returnhash;
   }
   
   # ------------------------------------------ get items from domain db files   
   
 sub get_dom {  sub get_dom {
     my ($namespace,$storearr,$udom,$uhome)=@_;      my ($namespace,$storearr,$udom,$uhome)=@_;
Line 1002  sub put_dom { Line 1049  sub put_dom {
     }      }
 }  }
   
   # --------------------- newput for items in db file owned by domainconfig user
   sub newput_dom {
       my ($namespace,$storehash,$udom) = @_;
       my $result;
       if (!$udom) {
           $udom=$env{'user.domain'};
       }
       if ($udom) {
           my $uname = &get_domainconfiguser($udom);
           $result = &newput($namespace,$storehash,$udom,$uname);
       }
       return $result;
   }
   
   # --------------------- delete for items in db file owned by domainconfig user
   sub del_dom {
       my ($namespace,$storearr,$udom)=@_;
       if (ref($storearr) eq 'ARRAY') {
           if (!$udom) {
               $udom=$env{'user.domain'};
           }
           if ($udom) {
               my $uname = &get_domainconfiguser($udom); 
               return &del($namespace,$storearr,$udom,$uname);
           }
       }
   }
   
   # ----------------------------------construct domainconfig user for a domain 
   sub get_domainconfiguser {
       my ($udom) = @_;
       return $udom.'-domainconfig';
   }
   
 sub retrieve_inst_usertypes {  sub retrieve_inst_usertypes {
     my ($udom) = @_;      my ($udom) = @_;
     my (%returnhash,@order);      my (%returnhash,@order);
Line 1270  sub get_domain_defaults { Line 1351  sub get_domain_defaults {
     my %domdefaults;      my %domdefaults;
     my %domconfig =      my %domconfig =
          &Apache::lonnet::get_dom('configuration',['defaults','quotas',           &Apache::lonnet::get_dom('configuration',['defaults','quotas',
                                   'requestcourses','inststatus'],$domain);                                    'requestcourses','inststatus',
                                     'coursedefaults'],$domain);
     if (ref($domconfig{'defaults'}) eq 'HASH') {      if (ref($domconfig{'defaults'}) eq 'HASH') {
         $domdefaults{'lang_def'} = $domconfig{'defaults'}{'lang_def'};           $domdefaults{'lang_def'} = $domconfig{'defaults'}{'lang_def'}; 
         $domdefaults{'auth_def'} = $domconfig{'defaults'}{'auth_def'};          $domdefaults{'auth_def'} = $domconfig{'defaults'}{'auth_def'};
Line 1296  sub get_domain_defaults { Line 1378  sub get_domain_defaults {
         }          }
     }      }
     if (ref($domconfig{'requestcourses'}) eq 'HASH') {      if (ref($domconfig{'requestcourses'}) eq 'HASH') {
         foreach my $item ('official','unofficial') {          foreach my $item ('official','unofficial','community') {
             $domdefaults{$item} = $domconfig{'requestcourses'}{$item};              $domdefaults{$item} = $domconfig{'requestcourses'}{$item};
         }          }
     }      }
Line 1305  sub get_domain_defaults { Line 1387  sub get_domain_defaults {
             $domdefaults{$item} = $domconfig{'inststatus'}{$item};              $domdefaults{$item} = $domconfig{'inststatus'}{$item};
         }          }
     }      }
       if (ref($domconfig{'coursedefaults'}) eq 'HASH') {
           foreach my $item ('canuse_pdfforms') {
               $domdefaults{$item} = $domconfig{'coursedefaults'}{$item};
           }
       }
     &Apache::lonnet::do_cache_new('domdefaults',$domain,\%domdefaults,      &Apache::lonnet::do_cache_new('domdefaults',$domain,\%domdefaults,
                                   $cachetime);                                    $cachetime);
     return %domdefaults;      return %domdefaults;
Line 1490  sub getsection { Line 1577  sub getsection {
     # If there is a role which has expired, return it.      # If there is a role which has expired, return it.
     #      #
     $courseid = &courseid_to_courseurl($courseid);      $courseid = &courseid_to_courseurl($courseid);
     my %roleshash = &dump('roles',$udom,$unam,$courseid);      my $extra = &freeze_escape({'skipcheck' => 1});
       my %roleshash = &dump('roles',$udom,$unam,$courseid,undef,$extra);
     foreach my $key (keys(%roleshash)) {      foreach my $key (keys(%roleshash)) {
         next if ($key !~/^\Q$courseid\E(?:\/)*(\w+)*\_st$/);          next if ($key !~/^\Q$courseid\E(?:\/)*(\w+)*\_st$/);
         my $section=$1;          my $section=$1;
Line 1635  sub userenvironment { Line 1723  sub userenvironment {
     }      }
     $items=~s/\&$//;      $items=~s/\&$//;
     my %returnhash=();      my %returnhash=();
     my @answer=split(/\&/,      my $uhome = &homeserver($unam,$udom);
                 &reply('get:'.$udom.':'.$unam.':environment:'.$items,      unless ($uhome eq 'no_host') {
                       &homeserver($unam,$udom)));          my @answer=split(/\&/, 
     my $i;              &reply('get:'.$udom.':'.$unam.':environment:'.$items,$uhome));
     for ($i=0;$i<=$#what;$i++) {          if ($#answer==0 && $answer[0] =~ /^(con_lost|error:|no_such_host)/i) {
  $returnhash{$what[$i]}=&unescape($answer[$i]);              return %returnhash;
           }
           my $i;
           for ($i=0;$i<=$#what;$i++) {
       $returnhash{$what[$i]}=&unescape($answer[$i]);
           }
     }      }
     return %returnhash;      return %returnhash;
 }  }
Line 1836  sub ssi_body { Line 1929  sub ssi_body {
     if ($filelink=~/^https?\:/) {      if ($filelink=~/^https?\:/) {
        ($output,$response)=&externalssi($filelink);         ($output,$response)=&externalssi($filelink);
     } else {      } else {
          $filelink .= $filelink=~/\?/ ? '&' : '?';
          $filelink .= 'inhibitmenu=yes';
        ($output,$response)=&ssi($filelink,%form);         ($output,$response)=&ssi($filelink,%form);
     }      }
     $output=~s|//(\s*<!--)? BEGIN LON-CAPA Internal.+?// END LON-CAPA Internal\s*(-->)?\s||gs;      $output=~s|//(\s*<!--)? BEGIN LON-CAPA Internal.+?// END LON-CAPA Internal\s*(-->)?\s||gs;
Line 1879  sub ssi { Line 1974  sub ssi {
     &Apache::lonenc::check_encrypt(\$fn);      &Apache::lonenc::check_encrypt(\$fn);
     if (%form) {      if (%form) {
       $request=new HTTP::Request('POST',&absolute_url().$fn);        $request=new HTTP::Request('POST',&absolute_url().$fn);
       $request->content(join('&',map { &escape($_).'='.&escape($form{$_}) } keys %form));        $request->content(join('&',map { &escape($_).'='.&escape($form{$_}) } keys(%form)));
     } else {      } else {
       $request=new HTTP::Request('GET',&absolute_url().$fn);        $request=new HTTP::Request('GET',&absolute_url().$fn);
     }      }
Line 1977  sub process_coursefile { Line 2072  sub process_coursefile {
             print $fh $env{'form.'.$source};              print $fh $env{'form.'.$source};
             close($fh);              close($fh);
             if ($parser eq 'parse') {              if ($parser eq 'parse') {
                 my $parse_result = &extract_embedded_items($filepath.'/'.$fname,$allfiles,$codebase);                  my $mm = new File::MMagic;
                 unless ($parse_result eq 'ok') {                  my $mime_type = $mm->checktype_filename($filepath.'/'.$fname);
                     &logthis('Failed to parse '.$filepath.'/'.$fname.' for embedded media: '.$parse_result);                  if ($mime_type eq 'text/html') {
                       my $parse_result = &extract_embedded_items($filepath.'/'.$fname,$allfiles,$codebase);
                       unless ($parse_result eq 'ok') {
                           &logthis('Failed to parse '.$filepath.'/'.$fname.' for embedded media: '.$parse_result);
                       }
                 }                  }
             }              }
             $fetchresult= &reply('fetchuserfile:'.$docudom.'/'.$docuname.'/'.$file,              $fetchresult= &reply('fetchuserfile:'.$docudom.'/'.$docuname.'/'.$file,
Line 2056  sub clean_filename { Line 2155  sub clean_filename {
     $fname=~s/\.(\d+)(?=\.)/_$1/g;      $fname=~s/\.(\d+)(?=\.)/_$1/g;
     return $fname;      return $fname;
 }  }
 #This Function check if a Image max 400px width and height 500px. If not then scale the image down  # This Function checks if an Image's dimensions exceed either $resizewidth (width) 
   # or $resizeheight (height) - both pixels. If so, the image is scaled to produce an 
   # image with the same aspect ratio as the original, but with dimensions which do 
   # not exceed $resizewidth and $resizeheight.
    
 sub resizeImage {  sub resizeImage {
  my($img_url) = @_;      my ($img_path,$resizewidth,$resizeheight) = @_;
  my $ima = Image::Magick->new;                             my $ima = Image::Magick->new;
         $ima->Read($img_url);      my $resized;
  if($ima->Get('width') > 400)      if (-e $img_path) {
  {          $ima->Read($img_path);
  my $factor = $ima->Get('width')/400;          if (($resizewidth =~ /^\d+$/) && ($resizeheight > 0)) {
               $ima->Scale( width=>400, height=>$ima->Get('height')/$factor );              my $width = $ima->Get('width');
  }              my $height = $ima->Get('height');
  if($ima->Get('height') > 500)              if ($width > $resizewidth) {
         {          my $factor = $width/$resizewidth;
         my $factor = $ima->Get('height')/500;                  my $newheight = $height/$factor;
                 $ima->Scale( width=>$ima->Get('width')/$factor, height=>500);                  $ima->Scale(width=>$resizewidth,height=>$newheight);
         }                   $resized = 1;
               }
  $ima->Write($img_url);          }
 }          if (($resizeheight =~ /^\d+$/) && ($resizeheight > 0)) {
               my $width = $ima->Get('width');
 #Wrapper function for userphotoupload              my $height = $ima->Get('height');
 sub userphotoupload              if ($height > $resizeheight) {
 {                  my $factor = $height/$resizeheight;
  my($formname,$subdir) = @_;                  my $newwidth = $width/$factor;
  $upload_photo_form = 1;                  $ima->Scale(width=>$newwidth,height=>$resizeheight);
  return &userfileupload($formname,undef,$subdir);                  $resized = 1;
               }
           }
           if ($resized) {
               $ima->Write($img_path);
           }
       }
       return;
 }  }
   
 # --------------- Take an uploaded file and put it into the userfiles directory  # --------------- Take an uploaded file and put it into the userfiles directory
 # input: $formname - the contents of the file are in $env{"form.$formname"}  # input: $formname - the contents of the file are in $env{"form.$formname"}
 #                    the desired filenam is in $env{"form.$formname.filename"}  #                    the desired filename is in $env{"form.$formname.filename"}
 #        $coursedoc - if true up to the current course  #        $coursedoc - if true up to the current course
 #                     if false  #                     if false
 #        $subdir - directory in userfile to store the file into  #        $subdir - directory in userfile to store the file into
Line 2096  sub userphotoupload Line 2206  sub userphotoupload
 #        $dsetudom - domain for permanaent storage of uploaded file  #        $dsetudom - domain for permanaent storage of uploaded file
 #        $thumbwidth - width (pixels) of thumbnail to make for uploaded image   #        $thumbwidth - width (pixels) of thumbnail to make for uploaded image 
 #        $thumbheight - height (pixels) of thumbnail to make for uploaded image  #        $thumbheight - height (pixels) of thumbnail to make for uploaded image
   #        $resizewidth - width (pixels) to which to resize uploaded image
   #        $resizeheight - height (pixels) to which to resize uploaded image
 #   # 
 # output: url of file in userspace, or error: <message>   # output: url of file in userspace, or error: <message> 
 #             or /adm/notfound.html if failure to upload occurse  #             or /adm/notfound.html if failure to upload occurse
   
   
 sub userfileupload {  sub userfileupload {
     my ($formname,$coursedoc,$subdir,$parser,$allfiles,$codebase,$destuname,      my ($formname,$coursedoc,$subdir,$parser,$allfiles,$codebase,$destuname,
         $destudom,$thumbwidth,$thumbheight)=@_;          $destudom,$thumbwidth,$thumbheight,$resizewidth,$resizeheight)=@_;
     if (!defined($subdir)) { $subdir='unknown'; }      if (!defined($subdir)) { $subdir='unknown'; }
     my $fname=$env{'form.'.$formname.'.filename'};      my $fname=$env{'form.'.$formname.'.filename'};
     $fname=&clean_filename($fname);      $fname=&clean_filename($fname);
Line 2141  sub userfileupload { Line 2252  sub userfileupload {
         close($fh);          close($fh);
         return $fullpath.'/'.$fname;          return $fullpath.'/'.$fname;
     }      }
           if ($subdir eq 'scantron') {
           $fname = 'scantron_orig_'.$fname;
       } else {
 # Create the directory if not present  # Create the directory if not present
     $fname="$subdir/$fname";          $fname="$subdir/$fname";
       }
     if ($coursedoc) {      if ($coursedoc) {
  my $docuname=$env{'course.'.$env{'request.course.id'}.'.num'};   my $docuname=$env{'course.'.$env{'request.course.id'}.'.num'};
  my $docudom=$env{'course.'.$env{'request.course.id'}.'.domain'};   my $docudom=$env{'course.'.$env{'request.course.id'}.'.domain'};
         if ($env{'form.folder'} =~ m/^(default|supplemental)/) {          if ($env{'form.folder'} =~ m/^(default|supplemental)/) {
             return &finishuserfileupload($docuname,$docudom,              return &finishuserfileupload($docuname,$docudom,
  $formname,$fname,$parser,$allfiles,   $formname,$fname,$parser,$allfiles,
  $codebase,$thumbwidth,$thumbheight);   $codebase,$thumbwidth,$thumbheight,
                                            $resizewidth,$resizeheight);
         } else {          } else {
             $fname=$env{'form.folder'}.'/'.$fname;              $fname=$env{'form.folder'}.'/'.$fname;
             return &process_coursefile('uploaddoc',$docuname,$docudom,              return &process_coursefile('uploaddoc',$docuname,$docudom,
Line 2162  sub userfileupload { Line 2277  sub userfileupload {
         my $docudom=$destudom;          my $docudom=$destudom;
  return &finishuserfileupload($docuname,$docudom,$formname,$fname,   return &finishuserfileupload($docuname,$docudom,$formname,$fname,
      $parser,$allfiles,$codebase,       $parser,$allfiles,$codebase,
                                      $thumbwidth,$thumbheight);                                       $thumbwidth,$thumbheight,
                                        $resizewidth,$resizeheight);
                   
     } else {      } else {
         my $docuname=$env{'user.name'};          my $docuname=$env{'user.name'};
Line 2173  sub userfileupload { Line 2289  sub userfileupload {
         }          }
  return &finishuserfileupload($docuname,$docudom,$formname,$fname,   return &finishuserfileupload($docuname,$docudom,$formname,$fname,
      $parser,$allfiles,$codebase,       $parser,$allfiles,$codebase,
                                      $thumbwidth,$thumbheight);                                       $thumbwidth,$thumbheight,
                                        $resizewidth,$resizeheight);
     }      }
 }  }
   
 sub finishuserfileupload {  sub finishuserfileupload {
     my ($docuname,$docudom,$formname,$fname,$parser,$allfiles,$codebase,      my ($docuname,$docudom,$formname,$fname,$parser,$allfiles,$codebase,
         $thumbwidth,$thumbheight) = @_;          $thumbwidth,$thumbheight,$resizewidth,$resizeheight) = @_;
     my $path=$docudom.'/'.$docuname.'/';      my $path=$docudom.'/'.$docuname.'/';
     my $filepath=$perlvar{'lonDocRoot'};      my $filepath=$perlvar{'lonDocRoot'};
       
Line 2211  sub finishuserfileupload { Line 2328  sub finishuserfileupload {
     return '/adm/notfound.html';      return '/adm/notfound.html';
  }   }
  close(FH);   close(FH);
  if($upload_photo_form==1)          if ($resizewidth && $resizeheight) {
  {              my $mm = new File::MMagic;
  resizeImage($filepath.'/'.$file);              my $mime_type = $mm->checktype_filename($filepath.'/'.$file);
  $upload_photo_form = 0;              if ($mime_type =~ m{^image/}) {
           &resizeImage($filepath.'/'.$file,$resizewidth,$resizeheight);
               }  
  }   }
     }      }
     if ($parser eq 'parse') {      if ($parser eq 'parse') {
         my $parse_result = &extract_embedded_items($filepath.'/'.$file,$allfiles,          my $mm = new File::MMagic;
    $codebase);          my $mime_type = $mm->checktype_filename($filepath.'/'.$file);
         unless ($parse_result eq 'ok') {          if ($mime_type eq 'text/html') {
             &logthis('Failed to parse '.$filepath.$file.              my $parse_result = &extract_embedded_items($filepath.'/'.$file,
      ' for embedded media: '.$parse_result);                                                          $allfiles,$codebase);
               unless ($parse_result eq 'ok') {
                   &logthis('Failed to parse '.$filepath.$file.
              ' for embedded media: '.$parse_result); 
               }
         }          }
     }      }
     if (($thumbwidth =~ /^\d+$/) && ($thumbheight =~ /^\d+$/)) {      if (($thumbwidth =~ /^\d+$/) && ($thumbheight =~ /^\d+$/)) {
Line 2526  sub flushcourselogs { Line 2649  sub flushcourselogs {
 # Reverse lookup of domain roles (dc, ad, li, sc, au)  # Reverse lookup of domain roles (dc, ad, li, sc, au)
 #  #
     my %domrolebuffer = ();      my %domrolebuffer = ();
     foreach my $entry (keys %domainrolehash) {      foreach my $entry (keys(%domainrolehash)) {
         my ($role,$uname,$udom,$runame,$rudom,$rsec)=split(/:/,$entry);          my ($role,$uname,$udom,$runame,$rudom,$rsec)=split(/:/,$entry);
         if ($domrolebuffer{$rudom}) {          if ($domrolebuffer{$rudom}) {
             $domrolebuffer{$rudom}.='&'.&escape($entry).              $domrolebuffer{$rudom}.='&'.&escape($entry).
Line 2631  sub userrolelog { Line 2754  sub userrolelog {
     if (($trole=~/^ca/) || ($trole=~/^aa/) ||      if (($trole=~/^ca/) || ($trole=~/^aa/) ||
         ($trole=~/^in/) || ($trole=~/^cc/) ||          ($trole=~/^in/) || ($trole=~/^cc/) ||
         ($trole=~/^ep/) || ($trole=~/^cr/) ||          ($trole=~/^ep/) || ($trole=~/^cr/) ||
         ($trole=~/^ta/)) {          ($trole=~/^ta/) || ($trole=~/^co/)) {
        my (undef,$rudom,$runame,$rsec)=split(/\//,$area);         my (undef,$rudom,$runame,$rsec)=split(/\//,$area);
        $userrolehash         $userrolehash
          {$trole.':'.$username.':'.$domain.':'.$runame.':'.$rudom.':'.$rsec}           {$trole.':'.$username.':'.$domain.':'.$runame.':'.$rudom.':'.$rsec}
Line 2640  sub userrolelog { Line 2763  sub userrolelog {
     if (($env{'request.role'} =~ /dc\./) &&      if (($env{'request.role'} =~ /dc\./) &&
  (($trole=~/^au/) || ($trole=~/^in/) ||   (($trole=~/^au/) || ($trole=~/^in/) ||
  ($trole=~/^cc/) || ($trole=~/^ep/) ||   ($trole=~/^cc/) || ($trole=~/^ep/) ||
  ($trole=~/^cr/) || ($trole=~/^ta/))) {   ($trole=~/^cr/) || ($trole=~/^ta/) ||
            ($trole=~/^co/))) {
        $userrolehash         $userrolehash
          {$trole.':'.$username.':'.$domain.':'.$env{'user.name'}.':'.$env{'user.domain'}.':'}           {$trole.':'.$username.':'.$domain.':'.$env{'user.name'}.':'.$env{'user.domain'}.':'}
                     =$tend.':'.$tstart;                      =$tend.':'.$tstart;
Line 2661  sub courserolelog { Line 2785  sub courserolelog {
     if (($trole eq 'cc') || ($trole eq 'in') ||      if (($trole eq 'cc') || ($trole eq 'in') ||
         ($trole eq 'ep') || ($trole eq 'ad') ||          ($trole eq 'ep') || ($trole eq 'ad') ||
         ($trole eq 'ta') || ($trole eq 'st') ||          ($trole eq 'ta') || ($trole eq 'st') ||
         ($trole=~/^cr/) || ($trole eq 'gr')) {          ($trole=~/^cr/) || ($trole eq 'gr') ||
           ($trole eq 'co')) {
         if ($area =~ m-^/($match_domain)/($match_courseid)/?([^/]*)-) {          if ($area =~ m-^/($match_domain)/($match_courseid)/?([^/]*)-) {
             my $cdom = $1;              my $cdom = $1;
             my $cnum = $2;              my $cnum = $2;
Line 2681  sub courserolelog { Line 2806  sub courserolelog {
                 $storehash{'section'} = $sec;                  $storehash{'section'} = $sec;
             }              }
             &instructor_log($namespace,\%storehash,$delflag,$username,$domain,$cnum,$cdom);              &instructor_log($namespace,\%storehash,$delflag,$username,$domain,$cnum,$cdom);
               if (($trole ne 'st') || ($sec ne '')) {
                   &devalidate_cache_new('getcourseroles',$cdom.'_'.$cnum);
               }
         }          }
     }      }
     return;      return;
Line 2703  sub get_course_adv_roles { Line 2831  sub get_course_adv_roles {
     my %dumphash=      my %dumphash=
             &dump('nohist_userroles',$coursehash{'domain'},$coursehash{'num'});              &dump('nohist_userroles',$coursehash{'domain'},$coursehash{'num'});
     my $now=time;      my $now=time;
     foreach my $entry (keys %dumphash) {      my %privileged;
       foreach my $entry (keys(%dumphash)) {
  my ($tend,$tstart)=split(/\:/,$dumphash{$entry});   my ($tend,$tstart)=split(/\:/,$dumphash{$entry});
         if (($tstart) && ($tstart<0)) { next; }          if (($tstart) && ($tstart<0)) { next; }
         if (($tend) && ($tend<$now)) { next; }          if (($tend) && ($tend<$now)) { next; }
         if (($tstart) && ($now<$tstart)) { next; }          if (($tstart) && ($now<$tstart)) { next; }
         my ($role,$username,$domain,$section)=split(/\:/,$entry);          my ($role,$username,$domain,$section)=split(/\:/,$entry);
  if ($username eq '' || $domain eq '') { next; }   if ($username eq '' || $domain eq '') { next; }
  if ((&privileged($username,$domain)) &&           unless (ref($privileged{$domain}) eq 'HASH') {
     (!$nothide{$username.':'.$domain})) { next; }              my %dompersonnel =
                   &Apache::lonnet::get_domain_roles($domain,['dc'],$now,$now);
               $privileged{$domain} = {};
               foreach my $server (keys(%dompersonnel)) {
                   if (ref($dompersonnel{$server}) eq 'HASH') {
                       foreach my $user (keys(%{$dompersonnel{$server}})) {
                           my ($trole,$uname,$udom) = split(/:/,$user);
                           $privileged{$udom}{$uname} = 1;
                       }
                   }
               }
           }
           if ((exists($privileged{$domain}{$username})) && 
               (!$nothide{$username.':'.$domain})) { next; }
  if ($role eq 'cr') { next; }   if ($role eq 'cr') { next; }
         if ($codes) {          if ($codes) {
             if ($section) { $role .= ':'.$section; }              if ($section) { $role .= ':'.$section; }
Line 2738  sub get_my_roles { Line 2880  sub get_my_roles {
     unless (defined($uname)) { $uname=$env{'user.name'}; }      unless (defined($uname)) { $uname=$env{'user.name'}; }
     unless (defined($udom)) { $udom=$env{'user.domain'}; }      unless (defined($udom)) { $udom=$env{'user.domain'}; }
     my (%dumphash,%nothide);      my (%dumphash,%nothide);
     if ($context eq 'userroles') {       if ($context eq 'userroles') {
         %dumphash = &dump('roles',$udom,$uname);          my $extra = &freeze_escape({'skipcheck' => 1});
           %dumphash = &dump('roles',$udom,$uname,'.',undef,$extra);
     } else {      } else {
         %dumphash=          %dumphash=
             &dump('nohist_userroles',$udom,$uname);              &dump('nohist_userroles',$udom,$uname);
Line 2756  sub get_my_roles { Line 2899  sub get_my_roles {
     }      }
     my %returnhash=();      my %returnhash=();
     my $now=time;      my $now=time;
       my %privileged;
     foreach my $entry (keys(%dumphash)) {      foreach my $entry (keys(%dumphash)) {
         my ($role,$tend,$tstart);          my ($role,$tend,$tstart);
         if ($context eq 'userroles') {          if ($context eq 'userroles') {
Line 2804  sub get_my_roles { Line 2948  sub get_my_roles {
             }              }
         }          }
         if ($hidepriv) {          if ($hidepriv) {
             if ((&privileged($username,$domain)) &&              if ($context eq 'userroles') {
                 (!$nothide{$username.':'.$domain})) {                   if ((&privileged($username,$domain)) &&
                 next;                      (!$nothide{$username.':'.$domain})) {
                       next;
                   }
               } else {
                   unless (ref($privileged{$domain}) eq 'HASH') {
                       my %dompersonnel =
                           &Apache::lonnet::get_domain_roles($domain,['dc'],$now,$now);
                       $privileged{$domain} = {};
                       if (keys(%dompersonnel)) {
                           foreach my $server (keys(%dompersonnel)) {
                               if (ref($dompersonnel{$server}) eq 'HASH') {
                                   foreach my $user (keys(%{$dompersonnel{$server}})) {
                                       my ($trole,$uname,$udom) = split(/:/,$user);
                                       $privileged{$udom}{$uname} = $trole;
                                   }
                               }
                           }
                       }
                   }
                   if (exists($privileged{$domain}{$username})) {
                       if (!$nothide{$username.':'.$domain}) {
                           next;
                       }
                   }
             }              }
         }          }
         if ($withsec) {          if ($withsec) {
Line 2854  sub getannounce { Line 3021  sub getannounce {
   
 sub courseidput {  sub courseidput {
     my ($domain,$storehash,$coursehome,$caller) = @_;      my ($domain,$storehash,$coursehome,$caller) = @_;
       return unless (ref($storehash) eq 'HASH');
     my $outcome;      my $outcome;
     if ($caller eq 'timeonly') {      if ($caller eq 'timeonly') {
         my $cids = '';          my $cids = '';
Line 2892  sub courseidput { Line 3060  sub courseidput {
 sub courseiddump {  sub courseiddump {
     my ($domfilter,$descfilter,$sincefilter,$instcodefilter,$ownerfilter,      my ($domfilter,$descfilter,$sincefilter,$instcodefilter,$ownerfilter,
         $coursefilter,$hostidflag,$hostidref,$typefilter,$regexp_ok,          $coursefilter,$hostidflag,$hostidref,$typefilter,$regexp_ok,
         $selfenrollonly,$catfilter,$showhidden,$caller)=@_;          $selfenrollonly,$catfilter,$showhidden,$caller,$cloner,$cc_clone,
           $cloneonly,$createdbefore,$createdafter,$creationcontext,$domcloner)=@_;
     my $as_hash = 1;      my $as_hash = 1;
     my %returnhash;      my %returnhash;
     if (!$domfilter) { $domfilter=''; }      if (!$domfilter) { $domfilter=''; }
Line 2911  sub courseiddump { Line 3080  sub courseiddump {
                          ':'.&escape($coursefilter).':'.&escape($typefilter).                           ':'.&escape($coursefilter).':'.&escape($typefilter).
                          ':'.&escape($regexp_ok).':'.$as_hash.':'.                           ':'.&escape($regexp_ok).':'.$as_hash.':'.
                          &escape($selfenrollonly).':'.&escape($catfilter).':'.                           &escape($selfenrollonly).':'.&escape($catfilter).':'.
                          $showhidden.':'.$caller,$tryserver);                           $showhidden.':'.$caller.':'.&escape($cloner).':'.
                            &escape($cc_clone).':'.$cloneonly.':'.
                            &escape($createdbefore).':'.&escape($createdafter).':'.
                            &escape($creationcontext).':'.$domcloner,
                            $tryserver);
                 my @pairs=split(/\&/,$rep);                  my @pairs=split(/\&/,$rep);
                 foreach my $item (@pairs) {                  foreach my $item (@pairs) {
                     my ($key,$value)=split(/\=/,$item,2);                      my ($key,$value)=split(/\=/,$item,2);
Line 2926  sub courseiddump { Line 3099  sub courseiddump {
                         for (my $i=0; $i<@responses; $i++) {                          for (my $i=0; $i<@responses; $i++) {
                             $returnhash{$key}{$items[$i]} = &unescape($responses[$i]);                              $returnhash{$key}{$items[$i]} = &unescape($responses[$i]);
                         }                          }
                     }                       }
                 }                  }
             }              }
         }          }
Line 2934  sub courseiddump { Line 3107  sub courseiddump {
     return %returnhash;      return %returnhash;
 }  }
   
   sub courselastaccess {
       my ($cdom,$cnum,$hostidref) = @_;
       my %returnhash;
       if ($cdom && $cnum) {
           my $chome = &homeserver($cnum,$cdom);
           if ($chome ne 'no_host') {
               my $rep = &reply('courselastaccess:'.$cdom.':'.$cnum,$chome);
               &extract_lastaccess(\%returnhash,$rep);
           }
       } else {
           if (!$cdom) { $cdom=''; }
           my %libserv = &all_library();
           foreach my $tryserver (keys(%libserv)) {
               if (ref($hostidref) eq 'ARRAY') {
                   next unless (grep(/^\Q$tryserver\E$/,@{$hostidref}));
               } 
               if (($cdom eq '') || (&host_domain($tryserver) eq $cdom)) {
                   my $rep = &reply('courselastaccess:'.&host_domain($tryserver).':',$tryserver);
                   &extract_lastaccess(\%returnhash,$rep);
               }
           }
       }
       return %returnhash;
   }
   
   sub extract_lastaccess {
       my ($returnhash,$rep) = @_;
       if (ref($returnhash) eq 'HASH') {
           unless ($rep eq 'unknown_command' || $rep eq 'no_such_host' || 
                   $rep eq 'con_lost' || $rep eq 'rejected' || $rep eq 'refused' ||
                    $rep eq '') {
               my @pairs=split(/\&/,$rep);
               foreach my $item (@pairs) {
                   my ($key,$value)=split(/\=/,$item,2);
                   $key = &unescape($key);
                   next if ($key =~ /^error: 2 /);
                   $returnhash->{$key} = &thaw_unescape($value);
               }
           }
       }
       return;
   }
   
 # ---------------------------------------------------------- DC e-mail  # ---------------------------------------------------------- DC e-mail
   
 sub dcmailput {  sub dcmailput {
Line 2966  sub dcmaildump { Line 3182  sub dcmaildump {
   
 sub get_domain_roles {  sub get_domain_roles {
     my ($dom,$roles,$startdate,$enddate)=@_;      my ($dom,$roles,$startdate,$enddate)=@_;
     if (undef($startdate) || $startdate eq '') {      if ((!defined($startdate)) || ($startdate eq '')) {
         $startdate = '.';          $startdate = '.';
     }      }
     if (undef($enddate) || $enddate eq '') {      if ((!defined($enddate)) || ($enddate eq '')) {
         $enddate = '.';          $enddate = '.';
     }      }
     my $rolelist;      my $rolelist;
Line 3376  sub tmpreset { Line 3592  sub tmpreset {
   if (tie(%hash,'GDBM_File',    if (tie(%hash,'GDBM_File',
   $path.'/tmpstore_'.$stuname.'_'.$domain.'_'.$namespace.'.db',    $path.'/tmpstore_'.$stuname.'_'.$domain.'_'.$namespace.'.db',
   &GDBM_WRCREAT(),0640)) {    &GDBM_WRCREAT(),0640)) {
     foreach my $key (keys %hash) {      foreach my $key (keys(%hash)) {
       if ($key=~ /:$symb/) {        if ($key=~ /:$symb/) {
  delete($hash{$key});   delete($hash{$key});
       }        }
Line 3659  sub privileged { Line 3875  sub privileged {
     my ($username,$domain)=@_;      my ($username,$domain)=@_;
     my $rolesdump=&reply("dump:$domain:$username:roles",      my $rolesdump=&reply("dump:$domain:$username:roles",
  &homeserver($username,$domain));   &homeserver($username,$domain));
     if (($rolesdump eq 'con_lost') || ($rolesdump eq '')) { return 0; }      if (($rolesdump eq 'con_lost') || ($rolesdump eq '') || 
           ($rolesdump =~ /^error:/)) {
           return 0;
       }
     my $now=time;      my $now=time;
     if ($rolesdump ne '') {      if ($rolesdump ne '') {
         foreach my $entry (split(/&/,$rolesdump)) {          foreach my $entry (split(/&/,$rolesdump)) {
Line 3687  sub privileged { Line 3906  sub privileged {
   
 sub rolesinit {  sub rolesinit {
     my ($domain,$username,$authhost)=@_;      my ($domain,$username,$authhost)=@_;
     my %userroles;      my $now=time;
       my %userroles = ('user.login.time' => $now);
     my $rolesdump=reply("dump:$domain:$username:roles",$authhost);      my $rolesdump=reply("dump:$domain:$username:roles",$authhost);
     if (($rolesdump eq 'con_lost') || ($rolesdump eq '')) { return \%userroles; }      if (($rolesdump eq 'con_lost') || ($rolesdump eq '') || 
           ($rolesdump =~ /^error:/)) { 
           return \%userroles;
       }
     my %allroles=();      my %allroles=();
     my %allgroups=();         my %allgroups=();   
     my $now=time;  
     %userroles = ('user.login.time' => $now);  
     my $group_privs;      my $group_privs;
   
     if ($rolesdump ne '') {      if ($rolesdump ne '') {
Line 3759  sub custom_roleprivs { Line 3980  sub custom_roleprivs {
         if (($rdummy ne 'con_lost') && ($roledef ne '')) {          if (($rdummy ne 'con_lost') && ($roledef ne '')) {
             my ($syspriv,$dompriv,$coursepriv)=split(/\_/,$roledef);              my ($syspriv,$dompriv,$coursepriv)=split(/\_/,$roledef);
             if (defined($syspriv)) {              if (defined($syspriv)) {
                   if ($trest =~ /^$match_community$/) {
                       $syspriv =~ s/bre\&S//; 
                   }
                 $$allroles{'cm./'}.=':'.$syspriv;                  $$allroles{'cm./'}.=':'.$syspriv;
                 $$allroles{$spec.'./'}.=':'.$syspriv;                  $$allroles{$spec.'./'}.=':'.$syspriv;
             }              }
Line 3807  sub standard_roleprivs { Line 4031  sub standard_roleprivs {
 }  }
   
 sub set_userprivs {  sub set_userprivs {
     my ($userroles,$allroles,$allgroups) = @_;       my ($userroles,$allroles,$allgroups,$groups_roles) = @_; 
     my $author=0;      my $author=0;
     my $adv=0;      my $adv=0;
     my %grouproles = ();      my %grouproles = ();
     if (keys(%{$allgroups}) > 0) {      if (keys(%{$allgroups}) > 0) {
         foreach my $role (keys %{$allroles}) {          my @groupkeys;
             my ($trole,$area,$sec,$extendedarea);          foreach my $role (keys(%{$allroles})) {
             if ($role =~ m-^(\w+|cr/$match_domain/$match_username/\w+)\.(/$match_domain/$match_courseid)(/?\w*)\.-) {              push(@groupkeys,$role);
                 $trole = $1;          }
                 $area = $2;          if (ref($groups_roles) eq 'HASH') {
                 $sec = $3;              foreach my $key (keys(%{$groups_roles})) {
                 $extendedarea = $area.$sec;                  unless (grep(/^\Q$key\E$/,@groupkeys)) {
                 if (exists($$allgroups{$area})) {                      push(@groupkeys,$key);
                     foreach my $group (keys(%{$$allgroups{$area}})) {                  }
                         my $spec = $trole.'.'.$extendedarea;              }
                         $grouproles{$spec.'.'.$area.'/'.$group} =           }
                                                 $$allgroups{$area}{$group};          if (@groupkeys > 0) {
               foreach my $role (@groupkeys) {
                   my ($trole,$area,$sec,$extendedarea);
                   if ($role =~ m-^(\w+|cr/$match_domain/$match_username/\w+)\.(/$match_domain/$match_courseid)(/?\w*)\.-) {
                       $trole = $1;
                       $area = $2;
                       $sec = $3;
                       $extendedarea = $area.$sec;
                       if (exists($$allgroups{$area})) {
                           foreach my $group (keys(%{$$allgroups{$area}})) {
                               my $spec = $trole.'.'.$extendedarea;
                               $grouproles{$spec.'.'.$area.'/'.$group} = 
                                                     $$allgroups{$area}{$group};
                           }
                     }                      }
                 }                  }
             }              }
Line 3855  sub set_userprivs { Line 4092  sub set_userprivs {
     return ($author,$adv);      return ($author,$adv);
 }  }
   
   sub role_status {
       my ($rolekey,$then,$refresh,$now,$role,$where,$trolecode,$tstatus,$tstart,$tend) = @_;
       my @pwhere = ();
       if (exists($env{$rolekey}) && $env{$rolekey} ne '') {
           (undef,undef,$$role,@pwhere)=split(/\./,$rolekey);
           unless (!defined($$role) || $$role eq '') {
               $$where=join('.',@pwhere);
               $$trolecode=$$role.'.'.$$where;
               ($$tstart,$$tend)=split(/\./,$env{$rolekey});
               $$tstatus='is';
               if ($$tstart && $$tstart>$then) {
                   $$tstatus='future';
                   if ($$tstart<$now) {
                       if ($$tstart && $$tstart>$refresh) {
                           if (($$where ne '') && ($$role ne '')) {
                               my (%allroles,%allgroups,$group_privs,
                                   %groups_roles,@rolecodes);
                               my %userroles = (
                                   'user.role.'.$$role.'.'.$$where => $$tstart.'.'.$$tend
                               );
                               @rolecodes = ('cm');
                               my $spec=$$role.'.'.$$where;
                               my ($tdummy,$tdomain,$trest)=split(/\//,$$where);
                               if ($$role =~ /^cr\//) {
                                   &custom_roleprivs(\%allroles,$$role,$tdomain,$trest,$spec,$$where);
                                   push(@rolecodes,'cr');
                               } elsif ($$role eq 'gr') {
                                   push(@rolecodes,$$role);
                                   my %rolehash = &get('roles',[$$where.'_'.$$role],$env{'user.domain'},
                                                       $env{'user.name'});
                                   my ($trole) = split('_',$rolehash{$$where.'_'.$$role},2);
                                   (undef,my $group_privs) = split(/\//,$trole);
                                   $group_privs = &unescape($group_privs);
                                   &group_roleprivs(\%allgroups,$$where,$group_privs,$$tend,$$tstart);
                                   my %course_roles = &get_my_roles($env{'user.name'},$env{'user.domain'},'userroles',['active'],['cc','co','in','ta','ep','ad','st','cr'],[$tdomain],1);
                                   if (keys(%course_roles) > 0) {
                                       my ($tnum) = ($trest =~ /^($match_courseid)/);
                                       if ($tdomain ne '' && $tnum ne '') {
                                           foreach my $key (keys(%course_roles)) {
                                               if ($key =~ /^\Q$tnum\E:\Q$tdomain\E:([^:]+):?([^:]*)/) {
                                                   my $crsrole = $1;
                                                   my $crssec = $2;
                                                   if ($crsrole =~ /^cr/) {
                                                       unless (grep(/^cr$/,@rolecodes)) {
                                                           push(@rolecodes,'cr');
                                                       }
                                                   } else {
                                                       unless(grep(/^\Q$crsrole\E$/,@rolecodes)) {
                                                           push(@rolecodes,$crsrole);
                                                       }
                                                   }
                                                   my $rolekey = $crsrole.'./'.$tdomain.'/'.$tnum;
                                                   if ($crssec ne '') {
                                                       $rolekey .= '/'.$crssec;
                                                   }
                                                   $rolekey .= './';
                                                   $groups_roles{$rolekey} = \@rolecodes;
                                               }
                                           }
                                       }
                                   }
                               } else {
                                   push(@rolecodes,$$role);
                                   &standard_roleprivs(\%allroles,$$role,$tdomain,$spec,$trest,$$where);
                               }
                               my ($author,$adv)= &set_userprivs(\%userroles,\%allroles,\%allgroups,\%groups_roles);
                               &appenv(\%userroles,\@rolecodes);
                               &log($env{'user.domain'},$env{'user.name'},$env{'user.home'},"Role ".$role);
                           }
                       }
                       $$tstatus = 'is';
                   }
               }
               if ($$tend) {
                   if ($$tend<$then) {
                       $$tstatus='expired';
                   } elsif ($$tend<$now) {
                       $$tstatus='will_not';
                   }
               }
           }
       }
   }
   
   sub check_adhoc_privs {
       my ($cdom,$cnum,$then,$refresh,$now,$checkrole,$caller) = @_;
       my $cckey = 'user.role.'.$checkrole.'./'.$cdom.'/'.$cnum;
       if ($env{$cckey}) {
           my ($role,$where,$trolecode,$tstart,$tend,$tremark,$tstatus,$tpstart,$tpend);
           &role_status($cckey,$then,$refresh,$now,\$role,\$where,\$trolecode,\$tstatus,\$tstart,\$tend);
           unless (($tstatus eq 'is') || ($tstatus eq 'will_not')) {
               &set_adhoc_privileges($cdom,$cnum,$checkrole,$caller);
           }
       } else {
           &set_adhoc_privileges($cdom,$cnum,$checkrole,$caller);
       }
   }
   
   sub set_adhoc_privileges {
   # role can be cc or ca
       my ($dcdom,$pickedcourse,$role,$caller) = @_;
       my $area = '/'.$dcdom.'/'.$pickedcourse;
       my $spec = $role.'.'.$area;
       my %userroles = &set_arearole($role,$area,'','',$env{'user.domain'},
                                     $env{'user.name'});
       my %ccrole = ();
       &standard_roleprivs(\%ccrole,$role,$dcdom,$spec,$pickedcourse,$area);
       my ($author,$adv)= &set_userprivs(\%userroles,\%ccrole);
       &appenv(\%userroles,[$role,'cm']);
       &log($env{'user.domain'},$env{'user.name'},$env{'user.home'},"Role ".$role);
       unless ($caller eq 'constructaccess' && $env{'request.course.id'}) {
           &appenv( {'request.role'        => $spec,
                     'request.role.domain' => $dcdom,
                     'request.course.sec'  => ''
                    }
                  );
           my $tadv=0;
           if (&allowed('adv') eq 'F') { $tadv=1; }
           &appenv({'request.role.adv'    => $tadv});
       }
   }
   
 # --------------------------------------------------------------- get interface  # --------------------------------------------------------------- get interface
   
 sub get {  sub get {
Line 3901  sub del { Line 4260  sub del {
 # -------------------------------------------------------------- dump interface  # -------------------------------------------------------------- dump interface
   
 sub dump {  sub dump {
     my ($namespace,$udomain,$uname,$regexp,$range)=@_;      my ($namespace,$udomain,$uname,$regexp,$range,$extra)=@_;
     if (!$udomain) { $udomain=$env{'user.domain'}; }      if (!$udomain) { $udomain=$env{'user.domain'}; }
     if (!$uname) { $uname=$env{'user.name'}; }      if (!$uname) { $uname=$env{'user.name'}; }
     my $uhome=&homeserver($uname,$udomain);      my $uhome=&homeserver($uname,$udomain);
Line 3910  sub dump { Line 4269  sub dump {
     } else {      } else {
  $regexp='.';   $regexp='.';
     }      }
     my $rep=&reply("dump:$udomain:$uname:$namespace:$regexp:$range",$uhome);      my $rep=&reply("dump:$udomain:$uname:$namespace:$regexp:$range:$extra",$uhome);
     my @pairs=split(/\&/,$rep);      my @pairs=split(/\&/,$rep);
     my %returnhash=();      my %returnhash=();
     foreach my $item (@pairs) {      foreach my $item (@pairs) {
Line 4315  sub get_portfolio_access { Line 4674  sub get_portfolio_access {
                 my (%allgroups,%allroles);                   my (%allgroups,%allroles); 
                 my ($start,$end,$role,$sec,$group);                  my ($start,$end,$role,$sec,$group);
                 foreach my $envkey (%env) {                  foreach my $envkey (%env) {
                     if ($envkey =~ m-^user\.role\.(gr|cc|in|ta|ep|st)\./($match_domain)/($match_courseid)/?([^/]*)$-) {                      if ($envkey =~ m-^user\.role\.(gr|cc|co|in|ta|ep|ad|st)\./($match_domain)/($match_courseid)/?([^/]*)$-) {
                         my $cid = $2.'_'.$3;                           my $cid = $2.'_'.$3; 
                         if ($1 eq 'gr') {                          if ($1 eq 'gr') {
                             $group = $4;                              $group = $4;
Line 4464  sub usertools_access { Line 4823  sub usertools_access {
         %tools = (          %tools = (
                       official   => 1,                        official   => 1,
                       unofficial => 1,                        unofficial => 1,
                         community  => 1,
                  );                   );
     } else {      } else {
         %tools = (          %tools = (
Line 4496  sub usertools_access { Line 4856  sub usertools_access {
         $toolstatus = $env{'environment.'.$context.'.'.$tool};          $toolstatus = $env{'environment.'.$context.'.'.$tool};
         $inststatus = $env{'environment.inststatus'};          $inststatus = $env{'environment.inststatus'};
     } else {      } else {
         my %userenv = &userenvironment($udom,$uname,$context.'.'.$tool);          my %userenv = &userenvironment($udom,$uname,$context.'.'.$tool,'inststatus');
         $toolstatus = $userenv{$context.'.'.$tool};          $toolstatus = $userenv{$context.'.'.$tool};
         $inststatus = $userenv{'inststatus'};          $inststatus = $userenv{'inststatus'};
     }      }
Line 4562  sub usertools_access { Line 4922  sub usertools_access {
     }      }
 }  }
   
   sub is_course_owner {
       my ($cdom,$cnum,$udom,$uname) = @_;
       if (($udom eq '') || ($uname eq '')) {
           $udom = $env{'user.domain'};
           $uname = $env{'user.name'};
       }
       unless (($udom eq '') || ($uname eq '')) {
           if (exists($env{'course.'.$cdom.'_'.$cnum.'.internal.courseowner'})) {
               if ($env{'course.'.$cdom.'_'.$cnum.'.internal.courseowner'} eq $uname.':'.$udom) {
                   return 1;
               } else {
                   my %courseinfo = &Apache::lonnet::coursedescription($cdom.'/'.$cnum);
                   if ($courseinfo{'internal.courseowner'} eq $uname.':'.$udom) {
                       return 1;
                   }
               }
           }
       }
       return;
   }
   
 sub is_advanced_user {  sub is_advanced_user {
     my ($udom,$uname) = @_;      my ($udom,$uname) = @_;
       if ($udom ne '' && $uname ne '') {
           if (($udom eq $env{'user.domain'}) && ($uname eq $env{'user.name'})) {
               return $env{'user.adv'};  
           }
       }
     my %roleshash = &get_my_roles($uname,$udom,'userroles',undef,undef,undef,1);      my %roleshash = &get_my_roles($uname,$udom,'userroles',undef,undef,undef,1);
     my %allroles;      my %allroles;
     my $is_adv;      my $is_adv;
Line 4597  sub is_advanced_user { Line 4983  sub is_advanced_user {
     return $is_adv;      return $is_adv;
 }  }
   
   sub check_can_request {
       my ($dom,$can_request,$request_domains) = @_;
       my $canreq = 0;
       my ($types,$typename) = &Apache::loncommon::course_types();
       my @options = ('approval','validate','autolimit');
       my $optregex = join('|',@options);
       if ((ref($can_request) eq 'HASH') && (ref($types) eq 'ARRAY')) {
           foreach my $type (@{$types}) {
               if (&usertools_access($env{'user.name'},
                                     $env{'user.domain'},
                                     $type,undef,'requestcourses')) {
                   $canreq ++;
                   if (ref($request_domains) eq 'HASH') {
                       push(@{$request_domains->{$type}},$env{'user.domain'});
                   }
                   if ($dom eq $env{'user.domain'}) {
                       $can_request->{$type} = 1;
                   }
               }
               if ($env{'environment.reqcrsotherdom.'.$type} ne '') {
                   my @curr = split(',',$env{'environment.reqcrsotherdom.'.$type});
                   if (@curr > 0) {
                       foreach my $item (@curr) {
                           if (ref($request_domains) eq 'HASH') {
                               my ($otherdom) = ($item =~ /^($match_domain):($optregex)(=?\d*)$/);
                               if ($otherdom ne '') {
                                   if (ref($request_domains->{$type}) eq 'ARRAY') {
                                       unless (grep(/^\Q$otherdom\E$/,@{$request_domains->{$type}})) {
                                           push(@{$request_domains->{$type}},$otherdom);
                                       }
                                   } else {
                                       push(@{$request_domains->{$type}},$otherdom);
                                   }
                               }
                           }
                       }
                       unless($dom eq $env{'user.domain'}) {
                           $canreq ++;
                           if (grep(/^\Q$dom\E:($optregex)(=?\d*)$/,@curr)) {
                               $can_request->{$type} = 1;
                           }
                       }
                   }
               }
           }
       }
       return $canreq;
   }
   
 # ---------------------------------------------- Custom access rule evaluation  # ---------------------------------------------- Custom access rule evaluation
   
 sub customaccess {  sub customaccess {
Line 4751  sub allowed { Line 5186  sub allowed {
     my $statecond=0;      my $statecond=0;
     my $courseprivid='';      my $courseprivid='';
   
       my $ownaccess;
       # Community Coordinator or Assistant Co-author browsing resource space.
       if (($priv eq 'bro') && ($env{'user.author'})) {
           if ($uri eq '') {
               $ownaccess = 1;
           } else {
               if (($env{'user.domain'} ne '') && ($env{'user.name'} ne '')) {
                   my $udom = $env{'user.domain'};
                   my $uname = $env{'user.name'};
                   if ($uri =~ m{^\Q$udom\E/?$}) {
                       $ownaccess = 1;
                   } elsif ($uri =~ m{^\Q$udom\E/\Q$uname\E/?}) {
                       unless ($uri =~ m{\.\./}) {
                           $ownaccess = 1;
                       }
                   } elsif (($udom ne 'public') && ($uname ne 'public')) {
                       my $now = time;
                       if ($uri =~ m{^([^/]+)/?$}) {
                           my $adom = $1;
                           foreach my $key (keys(%env)) {
                               if ($key =~ m{^user\.role\.(ca|aa)/\Q$adom\E}) {
                                   my ($start,$end) = split('.',$env{$key});
                                   if (($now >= $start) && (!$end || $end < $now)) {
                                       $ownaccess = 1;
                                       last;
                                   }
                               }
                           }
                       } elsif ($uri =~ m{^([^/]+)/([^/]+)/?}) {
                           my $adom = $1;
                           my $aname = $2;
                           foreach my $role ('ca','aa') { 
                               if ($env{"user.role.$role./$adom/$aname"}) {
                                   my ($start,$end) =
                                       split('.',$env{"user.role.$role./$adom/$aname"});
                                   if (($now >= $start) && (!$end || $end < $now)) {
                                       $ownaccess = 1;
                                       last;
                                   }
                               }
                           }
                       }
                   }
               }
           }
       }
   
 # Course  # Course
   
     if ($env{'user.priv.'.$env{'request.role'}.'./'}=~/\Q$priv\E\&([^\:]*)/) {      if ($env{'user.priv.'.$env{'request.role'}.'./'}=~/\Q$priv\E\&([^\:]*)/) {
        $thisallowed.=$1;          unless (($priv eq 'bro') && (!$ownaccess)) {
               $thisallowed.=$1;
           }
     }      }
   
 # Domain  # Domain
   
     if ($env{'user.priv.'.$env{'request.role'}.'./'.(split(/\//,$uri))[0].'/'}      if ($env{'user.priv.'.$env{'request.role'}.'./'.(split(/\//,$uri))[0].'/'}
        =~/\Q$priv\E\&([^\:]*)/) {         =~/\Q$priv\E\&([^\:]*)/) {
        $thisallowed.=$1;          unless (($priv eq 'bro') && (!$ownaccess)) {
               $thisallowed.=$1;
           }
     }      }
   
 # Course: uri itself is a course  # Course: uri itself is a course
Line 4771  sub allowed { Line 5257  sub allowed {
   
     if ($env{'user.priv.'.$env{'request.role'}.'.'.$courseuri}      if ($env{'user.priv.'.$env{'request.role'}.'.'.$courseuri}
        =~/\Q$priv\E\&([^\:]*)/) {         =~/\Q$priv\E\&([^\:]*)/) {
        $thisallowed.=$1;          unless (($priv eq 'bro') && (!$ownaccess)) {
               $thisallowed.=$1;
           }
     }      }
   
 # URI is an uploaded document for this course, default permissions don't matter  # URI is an uploaded document for this course, default permissions don't matter
Line 4911  sub allowed { Line 5399  sub allowed {
   
     my $envkey;      my $envkey;
     if ($thisallowed=~/L/) {      if ($thisallowed=~/L/) {
         foreach $envkey (keys %env) {          foreach $envkey (keys(%env)) {
            if ($envkey=~/^user\.role\.(st|ta)\.([^\.]*)/) {             if ($envkey=~/^user\.role\.(st|ta)\.([^\.]*)/) {
                my $courseid=$2;                 my $courseid=$2;
                my $roleid=$1.'.'.$2;                 my $roleid=$1.'.'.$2;
Line 5184  sub update_allusers_table { Line 5672  sub update_allusers_table {
                'generation='.&escape($names->{'generation'}).'%%'.                 'generation='.&escape($names->{'generation'}).'%%'.
                'permanentemail='.&escape($names->{'permanentemail'}).'%%'.                 'permanentemail='.&escape($names->{'permanentemail'}).'%%'.
                'id='.&escape($names->{'id'}),$homeserver);                 'id='.&escape($names->{'id'}),$homeserver);
     my $reply = &get_query_reply($queryid);      return;
     return $reply;  
 }  }
   
 # ------- Request retrieval of institutional classlists for course(s)  # ------- Request retrieval of institutional classlists for course(s)
Line 5202  sub fetch_enrollment_query { Line 5689  sub fetch_enrollment_query {
     }      }
     my $host=&hostname($homeserver);      my $host=&hostname($homeserver);
     my $cmd = '';      my $cmd = '';
     foreach my $affiliate (keys %{$affiliatesref}) {      foreach my $affiliate (keys(%{$affiliatesref})) {
         $cmd .= $affiliate.'='.join(",",@{$$affiliatesref{$affiliate}}).'%%';          $cmd .= $affiliate.'='.join(",",@{$$affiliatesref{$affiliate}}).'%%';
     }      }
     $cmd =~ s/%%$//;      $cmd =~ s/%%$//;
Line 5335  sub auto_run { Line 5822  sub auto_run {
   
 sub auto_get_sections {  sub auto_get_sections {
     my ($cnum,$cdom,$inst_coursecode) = @_;      my ($cnum,$cdom,$inst_coursecode) = @_;
     my $homeserver = &homeserver($cnum,$cdom);      my $homeserver;
     my @secs = ();      if (($cdom =~ /^$match_domain$/) && ($cnum =~ /^$match_courseid$/)) { 
     my $response=&unescape(&reply('autogetsections:'.$inst_coursecode.':'.$cdom,$homeserver));          $homeserver = &homeserver($cnum,$cdom);
     unless ($response eq 'refused') {      }
         @secs = split(/:/,$response);      if (!defined($homeserver)) { 
           if ($cdom =~ /^$match_domain$/) {
               $homeserver = &domain($cdom,'primary');
           }
       }
       my @secs;
       if (defined($homeserver)) {
           my $response=&unescape(&reply('autogetsections:'.$inst_coursecode.':'.$cdom,$homeserver));
           unless ($response eq 'refused') {
               @secs = split(/:/,$response);
           }
     }      }
     return @secs;      return @secs;
 }  }
Line 5358  sub auto_validate_courseID { Line 5855  sub auto_validate_courseID {
     return $response;      return $response;
 }  }
   
   sub auto_validate_instcode {
       my ($cnum,$cdom,$instcode,$owner) = @_;
       my ($homeserver,$response);
       if (($cdom =~ /^$match_domain$/) && ($cnum =~ /^$match_courseid$/)) {
           $homeserver = &homeserver($cnum,$cdom);
       }
       if (!defined($homeserver)) {
           if ($cdom =~ /^$match_domain$/) {
               $homeserver = &domain($cdom,'primary');
           }
       }
       $response=&unescape(&reply('autovalidateinstcode:'.$cdom.':'.
                           &escape($instcode).':'.&escape($owner),$homeserver));
       my ($outcome,$description) = map { &unescape($_); } split('&',$response,2);
       return ($outcome,$description);
   }
   
 sub auto_create_password {  sub auto_create_password {
     my ($cnum,$cdom,$authparam,$udom) = @_;      my ($cnum,$cdom,$authparam,$udom) = @_;
     my ($homeserver,$response);      my ($homeserver,$response);
Line 5472  sub auto_instcode_format { Line 5986  sub auto_instcode_format {
  push(@homeservers,$tryserver);   push(@homeservers,$tryserver);
     }      }
         }          }
       } elsif ($caller eq 'requests') {
           if ($codedom =~ /^$match_domain$/) {
               my $chome = &domain($codedom,'primary');
               unless ($chome eq 'no_host') {
                   push(@homeservers,$chome);
               }
           }
     } else {      } else {
         push(@homeservers,&homeserver($caller,$codedom));          push(@homeservers,&homeserver($caller,$codedom));
     }      }
Line 5529  sub auto_instcode_defaults { Line 6050  sub auto_instcode_defaults {
     }      }
   
     return $response;      return $response;
 }   }
   
   sub auto_possible_instcodes {
       my ($domain,$codetitles,$cat_titles,$cat_orders,$code_order) = @_;
       unless ((ref($codetitles) eq 'ARRAY') && (ref($cat_titles) eq 'HASH') && 
               (ref($cat_orders) eq 'HASH') && (ref($code_order) eq 'ARRAY')) {
           return;
       }
       my (@homeservers,$uhome);
       if (defined(&domain($domain,'primary'))) {
           $uhome=&domain($domain,'primary');
           push(@homeservers,&domain($domain,'primary'));
       } else {
           my %servers = &get_servers($domain,'library');
           foreach my $tryserver (keys(%servers)) {
               if (!grep(/^\Q$tryserver\E$/,@homeservers)) {
                   push(@homeservers,$tryserver);
               }
           }
       }
       my $response;
       foreach my $server (@homeservers) {
           $response=&reply('autopossibleinstcodes:'.$domain,$server);
           next if ($response =~ /(con_lost|error|no_such_host|refused)/);
           my ($codetitlestr,$codeorderstr,$cat_title,$cat_order) = 
               split(':',$response);
           @{$codetitles} = map { &unescape($_); } (split('&',$codetitlestr));
           @{$code_order} = map { &unescape($_); } (split('&',$codeorderstr));
           foreach my $item (split('&',$cat_title)) {   
               my ($name,$value)=split('=',$item);
               $cat_titles->{&unescape($name)}=&thaw_unescape($value);
           }
           foreach my $item (split('&',$cat_order)) {
               my ($name,$value)=split('=',$item);
               $cat_orders->{&unescape($name)}=&thaw_unescape($value);
           }
           return 'ok';
       }
       return $response;
   }
   
   sub auto_courserequest_checks {
       my ($dom) = @_;
       my ($homeserver,%validations);
       if ($dom =~ /^$match_domain$/) {
           $homeserver = &domain($dom,'primary');
       }
       unless ($homeserver eq 'no_host') {
           my $response=&reply('autocrsreqchecks:'.$dom,$homeserver);
           unless ($response =~ /(con_lost|error|no_such_host|refused)/) {
               my @items = split(/&/,$response);
               foreach my $item (@items) {
                   my ($key,$value) = split('=',$item);
                   $validations{&unescape($key)} = &thaw_unescape($value);
               }
           }
       }
       return %validations; 
   }
   
   sub auto_courserequest_validation {
       my ($dom,$owner,$crstype,$inststatuslist,$instcode,$instseclist) = @_;
       my ($homeserver,$response);
       if ($dom =~ /^$match_domain$/) {
           $homeserver = &domain($dom,'primary');
       }
       unless ($homeserver eq 'no_host') {  
             
           $response=&unescape(&reply('autocrsreqvalidation:'.$dom.':'.&escape($owner).
                                       ':'.&escape($crstype).':'.&escape($inststatuslist).
                                       ':'.&escape($instcode).':'.&escape($instseclist),
                                       $homeserver));
       }
       return $response;
   }
   
 sub auto_validate_class_sec {  sub auto_validate_class_sec {
     my ($cdom,$cnum,$owners,$inst_class) = @_;      my ($cdom,$cnum,$owners,$inst_class) = @_;
Line 5640  sub get_users_groups { Line 6235  sub get_users_groups {
     } else {        } else {  
         $grouplist = '';          $grouplist = '';
         my $courseurl = &courseid_to_courseurl($courseid);          my $courseurl = &courseid_to_courseurl($courseid);
         my %roleshash = &dump('roles',$udom,$uname,$courseurl);          my $extra = &freeze_escape({'skipcheck' => 1});
           my %roleshash = &dump('roles',$udom,$uname,$courseurl,undef,$extra);
         my $access_end = $env{'course.'.$courseid.          my $access_end = $env{'course.'.$courseid.
                               '.default_enrollment_end_date'};                                '.default_enrollment_end_date'};
         my $now = time;          my $now = time;
Line 5683  sub devalidate_getgroups_cache { Line 6279  sub devalidate_getgroups_cache {
   
 sub plaintext {  sub plaintext {
     my ($short,$type,$cid,$forcedefault) = @_;      my ($short,$type,$cid,$forcedefault) = @_;
     if ($short =~ /^cr/) {      if ($short =~ m{^cr/}) {
  return (split('/',$short))[-1];   return (split('/',$short))[-1];
     }      }
     if (!defined($cid)) {      if (!defined($cid)) {
         $cid = $env{'request.course.id'};          $cid = $env{'request.course.id'};
     }      }
     if (defined($cid) && ($env{'course.'.$cid.'.'.$short.'.plaintext'} ne '')) {  
         unless ($forcedefault) {  
             my $roletext = $env{'course.'.$cid.'.'.$short.'.plaintext'};   
             &Apache::lonlocal::mt_escape(\$roletext);  
             return &Apache::lonlocal::mt($roletext);  
         }  
     }  
     my %rolenames = (      my %rolenames = (
                       Course => 'std',                        Course    => 'std',
                       Group => 'alt1',                        Community => 'alt1',
                     );                      );
     if (defined($type) &&       if ($cid ne '') {
          defined($rolenames{$type}) &&           if ($env{'course.'.$cid.'.'.$short.'.plaintext'} ne '') {
          defined($prp{$short}{$rolenames{$type}})) {              unless ($forcedefault) {
                   my $roletext = $env{'course.'.$cid.'.'.$short.'.plaintext'}; 
                   &Apache::lonlocal::mt_escape(\$roletext);
                   return &Apache::lonlocal::mt($roletext);
               }
           }
       }
       if ((defined($type)) && (defined($rolenames{$type})) &&
           (defined($rolenames{$type})) && 
           (defined($prp{$short}{$rolenames{$type}}))) {
         return &Apache::lonlocal::mt($prp{$short}{$rolenames{$type}});          return &Apache::lonlocal::mt($prp{$short}{$rolenames{$type}});
     } else {      } elsif ($cid ne '') {
         return &Apache::lonlocal::mt($prp{$short}{'std'});          my $crstype = $env{'course.'.$cid.'.type'};
           if (($crstype ne '') && (defined($rolenames{$crstype})) &&
               (defined($prp{$short}{$rolenames{$crstype}}))) {
               return &Apache::lonlocal::mt($prp{$short}{$rolenames{$crstype}});
           }
     }      }
       return &Apache::lonlocal::mt($prp{$short}{'std'});
 }  }
   
 # ----------------------------------------------------------------- Assign Role  # ----------------------------------------------------------------- Assign Role
Line 5719  sub assignrole { Line 6322  sub assignrole {
         my $cwosec=$url;          my $cwosec=$url;
         $cwosec=~s/^\/($match_domain)\/($match_courseid)\/.*/$1\/$2/;          $cwosec=~s/^\/($match_domain)\/($match_courseid)\/.*/$1\/$2/;
  unless (&allowed('ccr',$cwosec)) {   unless (&allowed('ccr',$cwosec)) {
            &logthis('Refused custom assignrole: '.             my $refused = 1;
              $udom.' '.$uname.' '.$url.' '.$role.' '.$end.' '.$start.' by '.             if ($context eq 'requestcourses') {
     $env{'user.name'}.' at '.$env{'user.domain'});                 if (($env{'user.name'} ne '') && ($env{'user.domain'} ne '')) {
            return 'refused';                      if ($role =~ m{^cr/($match_domain)/($match_username)/([^/]+)$}) {
                          if (($1 eq $env{'user.domain'}) && ($2 eq $env{'user.name'})) {
                              my ($cdom,$cnum) = ($cwosec =~ m{^/?($match_domain)/($match_courseid)$});
                              my %crsenv = &userenvironment($cdom,$cnum,('internal.courseowner'));
                              if ($crsenv{'internal.courseowner'} eq
                                  $env{'user.name'}.':'.$env{'user.domain'}) {
                                  $refused = '';
                              }
                          }
                      }
                  }
              }
              if ($refused) {
                  &logthis('Refused custom assignrole: '.
                           $udom.' '.$uname.' '.$url.' '.$role.' '.$end.' '.$start.
                           ' by '.$env{'user.name'}.' at '.$env{'user.domain'});
                  return 'refused';
              }
         }          }
         $mrole='cr';          $mrole='cr';
     } elsif ($role =~ /^gr\//) {      } elsif ($role =~ /^gr\//) {
Line 5748  sub assignrole { Line 6368  sub assignrole {
                 $refused = 1;                  $refused = 1;
             }              }
             if ($refused) {              if ($refused) {
                 if (($selfenroll == 1) && ($role eq 'st') && ($udom eq $env{'user.domain'}) && ($uname eq $env{'user.name'})) {                  my ($cdom,$cnum) = ($cwosec =~ m{^/?($match_domain)/($match_courseid)$});
                   if (!$selfenroll && $context eq 'course') {
                       my %crsenv;
                       if ($role eq 'cc' || $role eq 'co') {
                           %crsenv = &userenvironment($cdom,$cnum,('internal.courseowner'));
                           if (($role eq 'cc') && ($cnum !~ /^$match_community$/)) {
                               if ($env{'request.role'} eq 'cc./'.$cdom.'/'.$cnum) {
                                   if ($crsenv{'internal.courseowner'} eq 
                                       $env{'user.name'}.':'.$env{'user.domain'}) {
                                       $refused = '';
                                   }
                               }
                           } elsif (($role eq 'co') && ($cnum =~ /^$match_community$/)) { 
                               if ($env{'request.role'} eq 'co./'.$cdom.'/'.$cnum) {
                                   if ($crsenv{'internal.courseowner'} eq 
                                       $env{'user.name'}.':'.$env{'user.domain'}) {
                                       $refused = '';
                                   }
                               }
                           }
                       }
                   } elsif (($selfenroll == 1) && ($role eq 'st') && ($udom eq $env{'user.domain'}) && ($uname eq $env{'user.name'})) {
                     $refused = '';                      $refused = '';
                 } else {                  } elsif ($context eq 'requestcourses') {
                       my @possroles = ('st','ta','ep','in','cc','co');
                       if ((grep(/^\Q$role\E$/,@possroles)) && ($env{'user.name'} ne '' && $env{'user.domain'} ne '')) {
                           my $wrongcc;
                           if ($cnum =~ /^$match_community$/) {
                               $wrongcc = 1 if ($role eq 'cc');
                           } else {
                               $wrongcc = 1 if ($role eq 'co');
                           }
                           unless ($wrongcc) {
                               my %crsenv = &userenvironment($cdom,$cnum,('internal.courseowner'));
                               if ($crsenv{'internal.courseowner'} eq 
                                    $env{'user.name'}.':'.$env{'user.domain'}) {
                                   $refused = '';
                               }
                           }
                       }
                   }
                   if ($refused) {
                     &logthis('Refused assignrole: '.$udom.' '.$uname.' '.$url.                      &logthis('Refused assignrole: '.$udom.' '.$uname.' '.$url.
                              ' '.$role.' '.$end.' '.$start.' by '.                               ' '.$role.' '.$end.' '.$start.' by '.
                $env{'user.name'}.' at '.$env{'user.domain'});                 $env{'user.name'}.' at '.$env{'user.domain'});
Line 5797  sub assignrole { Line 6456  sub assignrole {
             &Apache::longroup::group_changes($udom,$uname,$url,$role,$origend,              &Apache::longroup::group_changes($udom,$uname,$url,$role,$origend,
                                              $origstart,$selfenroll,$context);                                               $origstart,$selfenroll,$context);
         }          }
           if ($role eq 'cc') {
               &autoupdate_coowners($url,$end,$start,$uname,$udom);
           }
     }      }
     return $answer;      return $answer;
 }  }
   
   sub autoupdate_coowners {
       my ($url,$end,$start,$uname,$udom) = @_;
       my ($cdom,$cnum) = ($url =~ m{^/($match_domain)/($match_courseid)});
       if (($cdom ne '') && ($cnum ne '')) {
           my $now = time;
           my %domdesign = &Apache::loncommon::get_domainconf($cdom);
           if ($domdesign{$cdom.'.autoassign.co-owners'}) {
               my %coursehash = &coursedescription($cdom.'_'.$cnum);
               my $instcode = $coursehash{'internal.coursecode'};
               if ($instcode ne '') {
                   if (($start && $start <= $now) && ($end == 0) || ($end > $now)) {
                       unless ($coursehash{'internal.courseowner'} eq $uname.':'.$udom) {
                           my ($delcoowners,@newcoowners,$putresult,$delresult,$coowners);
                           my ($result,$desc) = &auto_validate_instcode($cnum,$cdom,$instcode,$uname.':'.$udom);
                           if ($result eq 'valid') {
                               if ($coursehash{'internal.co-owners'}) {
                                   foreach my $coowner (split(',',$coursehash{'internal.co-owners'})) {
                                       push(@newcoowners,$coowner);
                                   }
                                   unless (grep(/^\Q$uname\E:\Q$udom\E$/,@newcoowners)) {
                                       push(@newcoowners,$uname.':'.$udom);
                                   }
                                   @newcoowners = sort(@newcoowners);
                               } else {
                                   push(@newcoowners,$uname.':'.$udom);
                               }
                           } else {
                               if ($coursehash{'internal.co-owners'}) {
                                   foreach my $coowner (split(',',$coursehash{'internal.co-owners'})) {
                                       unless ($coowner eq $uname.':'.$udom) {
                                           push(@newcoowners,$coowner);
                                       }
                                   }
                                   unless (@newcoowners > 0) {
                                       $delcoowners = 1;
                                       $coowners = '';
                                   }
                               }
                           }
                           if (@newcoowners || $delcoowners) {
                               &store_coowners($cdom,$cnum,$coursehash{'home'},
                                               $delcoowners,@newcoowners);
                           }
                       }
                   }
               }
           }
       }
   }
   
   sub store_coowners {
       my ($cdom,$cnum,$chome,$delcoowners,@newcoowners) = @_;
       my $cid = $cdom.'_'.$cnum;
       my ($coowners,$delresult,$putresult);
       if (@newcoowners) {
           $coowners = join(',',@newcoowners);
           my %coownershash = (
                               'internal.co-owners' => $coowners,
                              );
           $putresult = &put('environment',\%coownershash,$cdom,$cnum);
           if ($putresult eq 'ok') {
               if ($env{'course.'.$cid.'.num'} eq $cnum) {
                   &appenv({'course.'.$cid.'.internal.co-owners' => $coowners});
               }
           }
       }
       if ($delcoowners) {
           $delresult = &Apache::lonnet::del('environment',['internal.co-owners'],$cdom,$cnum);
           if ($delresult eq 'ok') {
               if ($env{'course.'.$cid.'.internal.co-owners'}) {
                   &Apache::lonnet::delenv('course.'.$cid.'.internal.co-owners');
               }
           }
       }
       if (($putresult eq 'ok') || ($delresult eq 'ok')) {
           my %crsinfo =
               &Apache::lonnet::courseiddump($cdom,'.',1,'.','.',$cnum,undef,undef,'.');
           if (ref($crsinfo{$cid}) eq 'HASH') {
               $crsinfo{$cid}{'co-owners'} = \@newcoowners;
               my $cidput = &Apache::lonnet::courseidput($cdom,\%crsinfo,$chome,'notime');
           }
       }
   }
   
 # -------------------------------------------------- Modify user authentication  # -------------------------------------------------- Modify user authentication
 # Overrides without validation  # Overrides without validation
   
Line 5833  sub modifyuser { Line 6579  sub modifyuser {
     my ($udom,    $uname, $uid,      my ($udom,    $uname, $uid,
         $umode,   $upass, $first,          $umode,   $upass, $first,
         $middle,  $last,  $gene,          $middle,  $last,  $gene,
         $forceid, $desiredhome, $email, $inststatus)=@_;          $forceid, $desiredhome, $email, $inststatus, $candelete)=@_;
     $udom= &LONCAPA::clean_domain($udom);      $udom= &LONCAPA::clean_domain($udom);
     $uname=&LONCAPA::clean_username($uname);      $uname=&LONCAPA::clean_username($uname);
       my $showcandelete = 'none';
       if (ref($candelete) eq 'ARRAY') {
           if (@{$candelete} > 0) {
               $showcandelete = join(', ',@{$candelete});
           }
       }
     &logthis('Call to modify user '.$udom.', '.$uname.', '.$uid.', '.      &logthis('Call to modify user '.$udom.', '.$uname.', '.$uid.', '.
              $umode.', '.$first.', '.$middle.', '.               $umode.', '.$first.', '.$middle.', '.
      $last.', '.$gene.'(forceid: '.$forceid.')'.       $last.', '.$gene.'(forceid: '.$forceid.'; candelete: '.$showcandelete.')'.
              (defined($desiredhome) ? ' desiredhome = '.$desiredhome :               (defined($desiredhome) ? ' desiredhome = '.$desiredhome :
                                      ' desiredhome not specified').                                        ' desiredhome not specified'). 
              ' by '.$env{'user.name'}.' at '.$env{'user.domain'}.               ' by '.$env{'user.name'}.' at '.$env{'user.domain'}.
              ' in domain '.$env{'request.role.domain'});               ' in domain '.$env{'request.role.domain'});
     my $uhome=&homeserver($uname,$udom,'true');      my $uhome=&homeserver($uname,$udom,'true');
       my $newuser;
       if ($uhome eq 'no_host') {
           $newuser = 1;
       }
 # ----------------------------------------------------------------- Create User  # ----------------------------------------------------------------- Create User
     if (($uhome eq 'no_host') &&       if (($uhome eq 'no_host') && 
  (($umode && $upass) || ($umode eq 'localauth'))) {   (($umode && $upass) || ($umode eq 'localauth'))) {
Line 5896  sub modifyuser { Line 6652  sub modifyuser {
    ['firstname','middlename','lastname','generation','id',     ['firstname','middlename','lastname','generation','id',
                     'permanentemail','inststatus'],                      'permanentemail','inststatus'],
    $udom,$uname);     $udom,$uname);
     my %names;      my (%names,%oldnames);
     if ($tmp[0] =~ m/^error:.*/) {       if ($tmp[0] =~ m/^error:.*/) { 
         %names=();           %names=(); 
     } else {      } else {
         %names = @tmp;          %names = @tmp;
           %oldnames = %names;
     }      }
 #  #
 # Make sure to not trash student environment if instructor does not bother  # If name, email and/or uid are blank (e.g., because an uploaded file
 # to supply name and email information  # of users did not contain them), do not overwrite existing values
 #  # unless field is in $candelete array ref.
   #
       my @fields = ('firstname','middlename','lastname','generation',
                     'permanentemail','id');
       my %newvalues;
       if (ref($candelete) eq 'ARRAY') {
           foreach my $field (@fields) {
               if (grep(/^\Q$field\E$/,@{$candelete})) {
                   if ($field eq 'firstname') {
                       $names{$field} = $first;
                   } elsif ($field eq 'middlename') {
                       $names{$field} = $middle;
                   } elsif ($field eq 'lastname') {
                       $names{$field} = $last;
                   } elsif ($field eq 'generation') {
                       $names{$field} = $gene;
                   } elsif ($field eq 'permanentemail') {
                       $names{$field} = $email;
                   } elsif ($field eq 'id') {
                       $names{$field}  = $uid;
                   }
               }
           }
       }
   
     if ($first)  { $names{'firstname'}  = $first; }      if ($first)  { $names{'firstname'}  = $first; }
     if (defined($middle)) { $names{'middlename'} = $middle; }      if (defined($middle)) { $names{'middlename'} = $middle; }
     if ($last)   { $names{'lastname'}   = $last; }      if ($last)   { $names{'lastname'}   = $last; }
Line 5930  sub modifyuser { Line 6711  sub modifyuser {
             }              }
         }          }
     }      }
     my $reply = &put('environment', \%names, $udom,$uname);      my $logmsg = $udom.', '.$uname.', '.$uid.', '.
     if ($reply ne 'ok') { return 'error: '.$reply; }  
     my $sqlresult = &update_allusers_table($uname,$udom,\%names);  
     &devalidate_cache_new('namescache',$uname.':'.$udom);  
     my $logmsg = 'Success modifying user '.$udom.', '.$uname.', '.$uid.', '.  
                  $umode.', '.$first.', '.$middle.', '.                   $umode.', '.$first.', '.$middle.', '.
          $last.', '.$gene.', '.$email.', '.$inststatus;           $last.', '.$gene.', '.$email.', '.$inststatus;
     if ($env{'user.name'} ne '' && $env{'user.domain'}) {      if ($env{'user.name'} ne '' && $env{'user.domain'}) {
Line 5942  sub modifyuser { Line 6719  sub modifyuser {
     } else {      } else {
         $logmsg .= ' during self creation';          $logmsg .= ' during self creation';
     }      }
       my $changed;
       if ($newuser) {
           $changed = 1;
       } else {
           foreach my $field (@fields) {
               if ($names{$field} ne $oldnames{$field}) {
                   $changed = 1;
                   last;
               }
           }
       }
       unless ($changed) {
           $logmsg = 'No changes in user information needed for: '.$logmsg;
           &logthis($logmsg);
           return 'ok';
       }
       my $reply = &put('environment', \%names, $udom,$uname);
       if ($reply ne 'ok') {
           return 'error: '.$reply;
       }
       if ($names{'permanentemail'} ne $oldnames{'permanentemail'}) {
           &Apache::lonnet::devalidate_cache_new('emailscache',$uname.':'.$udom);
       }
       my $sqlresult = &update_allusers_table($uname,$udom,\%names);
       &devalidate_cache_new('namescache',$uname.':'.$udom);
       $logmsg = 'Success modifying user '.$logmsg;
     &logthis($logmsg);      &logthis($logmsg);
     return 'ok';      return 'ok';
 }  }
Line 6074  sub writecoursepref { Line 6877  sub writecoursepref {
   
 sub createcourse {  sub createcourse {
     my ($udom,$description,$url,$course_server,$nonstandard,$inst_code,      my ($udom,$description,$url,$course_server,$nonstandard,$inst_code,
         $course_owner,$crstype)=@_;          $course_owner,$crstype,$cnum,$context,$category)=@_;
     $url=&declutter($url);      $url=&declutter($url);
     my $cid='';      my $cid='';
     unless (&allowed('ccc',$udom)) {      if ($context eq 'requestcourses') {
           my $can_create = 0;
           my ($ownername,$ownerdom) = split(':',$course_owner);
           if ($udom eq $ownerdom) {
               if (&usertools_access($ownername,$ownerdom,$category,undef,
                                     $context)) {
                   $can_create = 1;
               }
           } else {
               my %userenv = &userenvironment($ownerdom,$ownername,'reqcrsotherdom.'.
                                              $category);
               if ($userenv{'reqcrsotherdom.'.$category} ne '') {
                   my @curr = split(',',$userenv{'reqcrsotherdom.'.$category});
                   if (@curr > 0) {
                       my @options = qw(approval validate autolimit);
                       my $optregex = join('|',@options);
                       if (grep(/^\Q$udom\E:($optregex)(=?\d*)$/,@curr)) {
                           $can_create = 1;
                       }
                   }
               }
           }
           if ($can_create) {
               unless ($ownername eq $env{'user.name'} && $ownerdom eq $env{'user.domain'}) {
                   unless (&allowed('ccc',$udom)) {
                       return 'refused'; 
                   }
               }
           } else {
               return 'refused';
           }
       } elsif (!&allowed('ccc',$udom)) {
         return 'refused';          return 'refused';
     }      }
 # ------------------------------------------------------------------- Create ID  # --------------------------------------------------------------- Get Unique ID
    my $uname=int(1+rand(9)).      my $uname;
        ('a'..'z','A'..'Z','0'..'9')[int(rand(62))].      if ($cnum =~ /^$match_courseid$/) {
        substr($$.time,0,5).unpack("H8",pack("I32",time)).          my $chome=&homeserver($cnum,$udom,'true');
        unpack("H2",pack("I32",int(rand(255)))).$perlvar{'lonHostID'};          if (($chome eq '') || ($chome eq 'no_host')) {
 # ----------------------------------------------- Make sure that does not exist              $uname = $cnum;
    my $uhome=&homeserver($uname,$udom,'true');          } else {
    unless (($uhome eq '') || ($uhome eq 'no_host')) {              $uname = &generate_coursenum($udom,$crstype);
        $uname=substr($$.time,0,5).unpack("H8",pack("I32",time)).          }
         unpack("H2",pack("I32",int(rand(255)))).$perlvar{'lonHostID'};      } else {
        $uhome=&homeserver($uname,$udom,'true');                 $uname = &generate_coursenum($udom,$crstype);
        unless (($uhome eq '') || ($uhome eq 'no_host')) {      }
            return 'error: unable to generate unique course-ID';      return $uname if ($uname =~ /^error/);
        }   # -------------------------------------------------- Check supplied server name
    }      if (!defined($course_server)) {
 # ------------------------------------------------ Check supplied server name          if (defined(&domain($udom,'primary'))) {
     $course_server = $env{'user.homeserver'} if (! defined($course_server));              $course_server = &domain($udom,'primary');
     if (! &is_library($course_server)) {          } else {
         return 'error:bad server name '.$course_server;              $course_server = $env{'user.home'}; 
           }
       }
       my %host_servers =
           &Apache::lonnet::get_servers($udom,'library');
       unless ($host_servers{$course_server}) {
           return 'error: invalid home server for course: '.$course_server;
     }      }
 # ------------------------------------------------------------- Make the course  # ------------------------------------------------------------- Make the course
     my $reply=&reply('encrypt:makeuser:'.$udom.':'.$uname.':none::',      my $reply=&reply('encrypt:makeuser:'.$udom.':'.$uname.':none::',
                       $course_server);                        $course_server);
     unless ($reply eq 'ok') { return 'error: '.$reply; }      unless ($reply eq 'ok') { return 'error: '.$reply; }
     $uhome=&homeserver($uname,$udom,'true');      my $uhome=&homeserver($uname,$udom,'true');
     if (($uhome eq '') || ($uhome eq 'no_host')) {       if (($uhome eq '') || ($uhome eq 'no_host')) { 
  return 'error: no such course';   return 'error: no such course';
     }      }
 # ----------------------------------------------------------------- Course made  # ----------------------------------------------------------------- Course made
 # log existence  # log existence
       my $now = time;
     my $newcourse = {      my $newcourse = {
                     $udom.'_'.$uname => {                      $udom.'_'.$uname => {
                                      description => $description,                                       description => $description,
                                      inst_code   => $inst_code,                                       inst_code   => $inst_code,
                                      owner       => $course_owner,                                       owner       => $course_owner,
                                      type        => $crstype,                                       type        => $crstype,
                                        creator     => $env{'user.name'}.':'.
                                                       $env{'user.domain'},
                                        created     => $now,
                                        context     => $context,
                                                 },                                                  },
                     };                      };
     &courseidput($udom,$newcourse,$uhome,'notime');      &courseidput($udom,$newcourse,$uhome,'notime');
Line 6140  ENDINITMAP Line 6985  ENDINITMAP
     }      }
 # ----------------------------------------------------------- Write preferences  # ----------------------------------------------------------- Write preferences
     &writecoursepref($udom.'_'.$uname,      &writecoursepref($udom.'_'.$uname,
                      ('description' => $description,                       ('description'              => $description,
                       'url'         => $topurl));                        'url'                      => $topurl,
                         'internal.creator'         => $env{'user.name'}.':'.
                                                       $env{'user.domain'},
                         'internal.created'         => $now,
                         'internal.creationcontext' => $context)
                       );
     return '/'.$udom.'/'.$uname;      return '/'.$udom.'/'.$uname;
 }  }
   
   # ------------------------------------------------------------------- Create ID
   sub generate_coursenum {
       my ($udom,$crstype) = @_;
       my $domdesc = &domain($udom);
       return 'error: invalid domain' if ($domdesc eq '');
       my $first;
       if ($crstype eq 'Community') {
           $first = '0';
       } else {
           $first = int(1+rand(9)); 
       } 
       my $uname=$first.
           ('a'..'z','A'..'Z','0'..'9')[int(rand(62))].
           substr($$.time,0,5).unpack("H8",pack("I32",time)).
           unpack("H2",pack("I32",int(rand(255)))).$perlvar{'lonHostID'};
   # ----------------------------------------------- Make sure that does not exist
       my $uhome=&homeserver($uname,$udom,'true');
       unless (($uhome eq '') || ($uhome eq 'no_host')) {
           if ($crstype eq 'Community') {
               $first = '0';
           } else {
               $first = int(1+rand(9));
           }
           $uname=$first.
                  ('a'..'z','A'..'Z','0'..'9')[int(rand(62))].
                  substr($$.time,0,5).unpack("H8",pack("I32",time)).
                  unpack("H2",pack("I32",int(rand(255)))).$perlvar{'lonHostID'};
           $uhome=&homeserver($uname,$udom,'true');
           unless (($uhome eq '') || ($uhome eq 'no_host')) {
               return 'error: unable to generate unique course-ID';
           }
       }
       return $uname;
   }
   
 sub is_course {  sub is_course {
     my ($cdom,$cnum) = @_;      my ($cdom,$cnum) = @_;
     my %courses = &courseiddump($cdom,'.',1,'.','.',$cnum,undef,      my %courses = &courseiddump($cdom,'.',1,'.','.',$cnum,undef,
Line 6155  sub is_course { Line 7040  sub is_course {
     return 0;      return 0;
 }  }
   
   sub store_userdata {
       my ($storehash,$datakey,$namespace,$udom,$uname) = @_;
       my $result;
       if ($datakey ne '') {
           if (ref($storehash) eq 'HASH') {
               if ($udom eq '' || $uname eq '') {
                   $udom = $env{'user.domain'};
                   $uname = $env{'user.name'};
               }
               my $uhome=&homeserver($uname,$udom);
               if (($uhome eq '') || ($uhome eq 'no_host')) {
                   $result = 'error: no_host';
               } else {
                   $storehash->{'ip'} = $ENV{'REMOTE_ADDR'};
                   $storehash->{'host'} = $perlvar{'lonHostID'};
   
                   my $namevalue='';
                   foreach my $key (keys(%{$storehash})) {
                       $namevalue.=&escape($key).'='.&freeze_escape($$storehash{$key}).'&';
                   }
                   $namevalue=~s/\&$//;
                   $result =  &reply("store:$env{'user.domain'}:$env{'user.name'}:".
                                     "$namespace:$datakey:$namevalue",$uhome);
               }
           } else {
               $result = 'error: data to store was not a hash reference'; 
           }
       } else {
           $result= 'error: invalid requestkey'; 
       }
       return $result;
   }
   
 # ---------------------------------------------------------- Assign Custom Role  # ---------------------------------------------------------- Assign Custom Role
   
 sub assigncustomrole {  sub assigncustomrole {
Line 6200  sub is_locked { Line 7118  sub is_locked {
     my ($file_name, $domain, $user) = @_;      my ($file_name, $domain, $user) = @_;
     my @check;      my @check;
     my $is_locked;      my $is_locked;
     push @check, $file_name;      push(@check,$file_name);
     my %locked = &get('file_permissions',\@check,      my %locked = &get('file_permissions',\@check,
       $env{'user.domain'},$env{'user.name'});        $env{'user.domain'},$env{'user.name'});
     my ($tmp)=keys(%locked);      my ($tmp)=keys(%locked);
Line 6217  sub is_locked { Line 7135  sub is_locked {
     } else {      } else {
         $is_locked = 'false';          $is_locked = 'false';
     }      }
       return $is_locked;
 }  }
   
 sub declutter_portfile {  sub declutter_portfile {
Line 7644  sub devalidate_title_cache { Line 8563  sub devalidate_title_cache {
     &devalidate_cache_new('title',$key);      &devalidate_cache_new('title',$key);
 }  }
   
   # ------------------------------------------------- Get the title of a course
   
   sub current_course_title {
       return $env{ 'course.' . $env{'request.course.id'} . '.description' };
   }
 # ------------------------------------------------- Get the title of a resource  # ------------------------------------------------- Get the title of a resource
   
 sub gettitle {  sub gettitle {
Line 7710  sub symblist { Line 8634  sub symblist {
     if (($env{'request.course.fn'}) && (%newhash)) {      if (($env{'request.course.fn'}) && (%newhash)) {
         if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',          if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
                       &GDBM_WRCREAT(),0640)) {                        &GDBM_WRCREAT(),0640)) {
     foreach my $url (keys %newhash) {      foreach my $url (keys(%newhash)) {
  next if ($url eq 'last_known'   next if ($url eq 'last_known'
  && $env{'form.no_update_last_known'});   && $env{'form.no_update_last_known'});
  $hash{declutter($url)}=&encode_symb($mapname,   $hash{declutter($url)}=&encode_symb($mapname,
Line 7747  sub symbverify { Line 8671  sub symbverify {
   
     if (tie(%bighash,'GDBM_File',$env{'request.course.fn'}.'.db',      if (tie(%bighash,'GDBM_File',$env{'request.course.fn'}.'.db',
                             &GDBM_READER(),0640)) {                              &GDBM_READER(),0640)) {
           if (($thisurl =~ m{^/adm/wrapper/ext/}) || ($thisurl =~ m{^ext/})) {
               $thisurl =~ s/\?.+$//;
           }
         my $ids=$bighash{'ids_'.&clutter($thisurl)};          my $ids=$bighash{'ids_'.&clutter($thisurl)};
         unless ($ids) {           unless ($ids) { 
            $ids=$bighash{'ids_/'.$thisurl};             $ids=$bighash{'ids_/'.$thisurl};
Line 7755  sub symbverify { Line 8682  sub symbverify {
 # ------------------------------------------------------------------- Has ID(s)  # ------------------------------------------------------------------- Has ID(s)
     foreach my $id (split(/\,/,$ids)) {      foreach my $id (split(/\,/,$ids)) {
        my ($mapid,$resid)=split(/\./,$id);         my ($mapid,$resid)=split(/\./,$id);
                  if ($thisfn =~ m{^/adm/wrapper/ext/}) {
                      $symb =~ s/\?.+$//;
                  }
                if (                 if (
   &symbclean(&declutter($bighash{'map_id_'.$mapid}).'___'.$resid.'___'.$thisfn)    &symbclean(&declutter($bighash{'map_id_'.$mapid}).'___'.$resid.'___'.$thisfn)
    eq $symb) {      eq $symb) { 
Line 8631  sub declutter { Line 9561  sub declutter {
     $thisfn=~s|^adm/wrapper/||;      $thisfn=~s|^adm/wrapper/||;
     $thisfn=~s|^adm/coursedocs/showdoc/||;      $thisfn=~s|^adm/coursedocs/showdoc/||;
     $thisfn=~s/^res\///;      $thisfn=~s/^res\///;
     $thisfn=~s/\?.+$//;      unless (($thisfn =~ /^ext/) || ($thisfn =~ /\.(page|sequence)___\d+___ext/)) {
           $thisfn=~s/\?.+$//;
       }
     return $thisfn;      return $thisfn;
 }  }
   
Line 8643  sub clutter { Line 9575  sub clutter {
  || $thisfn =~ m{^/adm/(includes|pages)} ) {    || $thisfn =~ m{^/adm/(includes|pages)} ) { 
        $thisfn='/res'.$thisfn;          $thisfn='/res'.$thisfn; 
     }      }
     if ($thisfn !~m|/adm|) {      if ($thisfn !~m|^/adm|) {
  if ($thisfn =~ m|/ext/|) {   if ($thisfn =~ m|^/ext/|) {
     $thisfn='/adm/wrapper'.$thisfn;      $thisfn='/adm/wrapper'.$thisfn;
  } else {   } else {
     my ($ext) = ($thisfn =~ /\.(\w+)$/);      my ($ext) = ($thisfn =~ /\.(\w+)$/);
Line 9048  sub get_dns { Line 9980  sub get_dns {
   
  return %iphost;   return %iphost;
     }      }
 }  
   
 #      #
 #  Given a DNS returns the loncapa host name for that DNS       #  Given a DNS returns the loncapa host name for that DNS 
 #       # 
 sub host_from_dns {      sub host_from_dns {
     my ($dns) = @_;          my ($dns) = @_;
     my @hosts;          my @hosts;
     my $ip;          my $ip;
   
     $ip = gethostbyname($dns); # Initial translation to IP is in net order.          if (exists($name_to_ip{$dns})) {
     if (length($ip) == 4) {               $ip = $name_to_ip{$dns};
  $ip   = &IO::Socket::inet_ntoa($ip);          }
  @hosts = get_hosts_from_ip($ip);          if (!$ip) {
  return $hosts[0];              $ip = gethostbyname($dns); # Initial translation to IP is in net order.
               if (length($ip) == 4) { 
           $ip   = &IO::Socket::inet_ntoa($ip);
               }
           }
           if ($ip) {
       @hosts = get_hosts_from_ip($ip);
       return $hosts[0];
           }
           return undef;
     }      }
     return undef;  
 }  }
   
 BEGIN {  BEGIN {
Line 9449  and course level Line 10389  and course level
   
 plaintext($short,$type,$cid,$forcedefault) : return value in %prp hash   plaintext($short,$type,$cid,$forcedefault) : return value in %prp hash 
 (rolesplain.tab); plain text explanation of a user role term.  (rolesplain.tab); plain text explanation of a user role term.
 $type is Course (default) or Group.  $type is Course (default) or Community.
 If $forcedefault evaluates to true, text returned will be default   If $forcedefault evaluates to true, text returned will be default 
 text for $type. Otherwise, if this is a course, the text returned   text for $type. Otherwise, if this is a course, the text returned 
 will be a custom name for the role (if defined in the course's   will be a custom name for the role (if defined in the course's 
Line 9496  modifyuserauth($udom,$uname,$umode,$upas Line 10436  modifyuserauth($udom,$uname,$umode,$upas
   
 =item *  =item *
   
 modifyuser($udom,$uname,$uid,$umode,$upass,$first,$middle,$last,$gene,  modifyuser($udom,$uname,$uid,$umode,$upass,$first,$middle,$last, $gene,
            $forceid,$desiredhome,$email,$inststatus) :              $forceid,$desiredhome,$email,$inststatus,$candelete) :
 modify user  
   will update user information (firstname,middlename,lastname,generation,
   permanentemail), and if forceid is true, student/employee ID also.
   A user's institutional affiliation(s) can also be updated.
   User information fields will not be overwritten with empty entries
   unless the field is included in the $candelete array reference.
   This array is included when a single user is modified via "Manage Users",
   or when Autoupdate.pl is run by cron in a domain.
   
 =item *  =item *
   
Line 9659  database) for a course Line 10606  database) for a course
   
 =item *  =item *
   
 createcourse($udom,$description,$url) : make/modify course  createcourse($udom,$description,$url,$course_server,$nonstandard,$inst_code,$course_owner,$crstype,$cnum) : make course
   
   =item *
   
   generate_coursenum($udom,$crstype) : get a unique (unused) course number in domain $udom for course type $crstype (Course or Community).
   
 =back  =back
   

Removed from v.1.990  
changed lines
  Added in v.1.1056.2.10


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>