Diff for /loncom/interface/courseprefs.pm between versions 1.99 and 1.108

version 1.99, 2022/02/01 23:13:19 version 1.108, 2022/04/05 12:27:39
Line 52  This module is used for configuration of Line 52  This module is used for configuration of
   
 =item process_changes()  =item process_changes()
   
   =item process_linkprot()
   
 =item get_sec_str()  =item get_sec_str()
   
 =item check_clone()  =item check_clone()
   
 =item store_changes()  =item store_changes()
   
   =item store_linkprot()
   
 =item update_env()  =item update_env()
   
 =item display_disallowed()  =item display_disallowed()
Line 220  use Apache::lonparmset; Line 224  use Apache::lonparmset;
 use Apache::courseclassifier;  use Apache::courseclassifier;
 use Apache::lonlocal;  use Apache::lonlocal;
 use LONCAPA qw(:DEFAULT :match);  use LONCAPA qw(:DEFAULT :match);
   use Crypt::CBC;
   
 my $registered_cleanup;  my $registered_cleanup;
 my $modified_courses;  my $modified_courses;
Line 365  sub handler { Line 370  sub handler {
     }      }
   
     my %values=&Apache::lonnet::dump('environment',$cdom,$cnum);      my %values=&Apache::lonnet::dump('environment',$cdom,$cnum);
     my %lti=&Apache::lonnet::dump('lti',$cdom,$cnum,undef,undef,undef,1);      my %linkprot=&Apache::lonnet::dump('lti',$cdom,$cnum,undef,undef,undef,1);
     my %ltienc = &Apache::lonnet::dump('nohist_ltienc',$cdom,$cnum,undef,undef,undef,1);      my %ltienc = &Apache::lonnet::dump('nohist_ltienc',$cdom,$cnum,undef,undef,undef,1);
     foreach my $id (keys(%lti)) {      foreach my $id (keys(%linkprot)) {
         if (ref($lti{$id}) eq 'HASH') {          if (ref($linkprot{$id}) eq 'HASH') {
             if (ref($ltienc{$id}) eq 'HASH') {              if (ref($ltienc{$id}) eq 'HASH') {
                 $values{'linkprotection'}{$id} = { %{$lti{$id}}, %{$ltienc{$id}} };                  $values{'linkprot'}{$id} = { %{$linkprot{$id}}, %{$ltienc{$id}} };
             } else {              } else {
                 $values{'linkprotection'}{$id} = $lti{$id};                  $values{'linkprot'}{$id} = $linkprot{$id};
             }              }
         }          }
         unless ($phase eq 'process') {          unless ($phase eq 'process') {
             if (ref($values{'linkprotection'}{$id}) eq 'HASH') {              if (ref($values{'linkprot'}{$id}) eq 'HASH') {
                 delete($values{'linkprotection'}{$id}{'secret'});                  delete($values{'linkprot'}{$id}{'secret'});
             }              }
         }          }
     }      }
     if ($lti{'lock'}) {      if ($linkprot{'lock'}) {
         delete($lti{'lock'});          delete($linkprot{'lock'});
     }      }
     my @prefs_order = ('courseinfo','localization','feedback','discussion',      my @prefs_order = ('courseinfo','localization','feedback','discussion',
                        'classlists','appearance','grading','printouts',                         'classlists','appearance','grading','printouts',
                        'menuitems','linkprotection','spreadsheet','bridgetasks',                         'menuitems','linkprot','spreadsheet','bridgetasks',
                        'lti','other');                         'lti','other');
   
     my %prefs = (      my %prefs = (
Line 578  sub handler { Line 583  sub handler {
                          menucollections => 'Menu collections',                           menucollections => 'Menu collections',
                                  },                                   },
                    },                     },
         'linkprotection' =>          'linkprot' =>
                    {                     {
                      text => 'Link protection',                       text => 'Link protection',
                      help => 'Course_Prefs_Linkprotection',                       help => 'Course_Prefs_Linkprotection',
Line 596  sub handler { Line 601  sub handler {
     );      );
     if (($phase eq 'process') && ($parm_permission->{'process'})) {      if (($phase eq 'process') && ($parm_permission->{'process'})) {
         my @allitems = &get_allitems(%prefs);          my @allitems = &get_allitems(%prefs);
         &Apache::lonconfigsettings::make_changes($r,$cdom,$phase,$context,          my $result = &Apache::lonconfigsettings::make_changes($r,$cdom,$phase,$context,
                                                  \@prefs_order,\%prefs,\%values,                                                                \@prefs_order,\%prefs,\%values,
                                                   $cnum,undef,\@allitems,                                                                $cnum,undef,\@allitems,
                                                   'coursepref',$parm_permission);                                                                'coursepref',$parm_permission);
           if ((ref($result) eq 'HASH') && (keys(%{$result}))) {
               $r->rflush();
               &devalidate_remote_courseprefs($cdom,$cnum,$result);
           }
     } elsif (($phase eq 'display') && ($parm_permission->{'display'})) {      } elsif (($phase eq 'display') && ($parm_permission->{'display'})) {
         my $noedit;          my $noedit;
         if (ref($parm_permission) eq 'HASH') {          if (ref($parm_permission) eq 'HASH') {
Line 793  sub print_config_box { Line 802  sub print_config_box {
         $output .= &print_lti($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype,$noedit);          $output .= &print_lti($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype,$noedit);
     } elsif ($action eq 'menuitems') {      } elsif ($action eq 'menuitems') {
         $output .= &print_menuitems('bottom',$cdom,$settings,$itemtext,\$rowtotal,$crstype,$noedit);          $output .= &print_menuitems('bottom',$cdom,$settings,$itemtext,\$rowtotal,$crstype,$noedit);
     } elsif ($action eq 'linkprotection') {      } elsif ($action eq 'linkprot') {
         $output .= &print_linkprotection($cdom,$cnum,$settings,\$rowtotal,$crstype,$noedit);          $output .= &print_linkprotection($cdom,$cnum,$settings,\$rowtotal,$crstype,$noedit,'course');
     } elsif ($action eq 'other') {      } elsif ($action eq 'other') {
         $output .= &print_other($cdom,$settings,$allitems,\$rowtotal,$crstype,$noedit);          $output .= &print_other($cdom,$settings,$allitems,\$rowtotal,$crstype,$noedit);
     }      }
Line 807  sub print_config_box { Line 816  sub print_config_box {
 }  }
   
 sub process_changes {  sub process_changes {
     my ($cdom,$cnum,$action,$values,$item,$changes,$allitems,$disallowed,$crstype) = @_;      my ($cdom,$cnum,$action,$values,$item,$changes,$allitems,$disallowed,$crstype,$lastactref) = @_;
     my (%newvalues,%lti,%ltienc,$errors);      my (%newvalues,$errors);
     if (ref($item) eq 'HASH') {      if (ref($item) eq 'HASH') {
         if (ref($changes) eq 'HASH') {          if (ref($changes) eq 'HASH') {
             my @ordered;              my @ordered;
Line 825  sub process_changes { Line 834  sub process_changes {
                         }                          }
                     }                      }
                 }                  }
             } elsif ($action eq 'linkprotection') {              } elsif ($action eq 'linkprot') {
                 if (ref($values->{$action}) eq 'HASH') {                  if (ref($values->{$action}) eq 'HASH') {
                     foreach my $id (keys(%{$values->{$action}})) {                      foreach my $id (keys(%{$values->{$action}})) {
                         if ($id =~ /^\d+$/) {                          if ($id =~ /^\d+$/) {
                             push(@ordered,$id);                              push(@ordered,$id);
                             unless (ref($values->{$action}->{$id}) eq 'HASH') {  
                                 $lti{$id} = '';  
                             }  
                         }                          }
                     }                      }
                 }                  }
Line 977  sub process_changes { Line 983  sub process_changes {
                     } elsif ($values->{'menucollections'}) {                      } elsif ($values->{'menucollections'}) {
                         $changes->{'menucollections'} = '';                          $changes->{'menucollections'} = '';
                     }                      }
                 } elsif ($action eq 'linkprotection') {                  } elsif ($action eq 'linkprot') {
                     my %menutitles = &ltimenu_titles();                      if (ref($values) eq 'HASH') {
                     my $switchserver = &check_switchserver($cdom,$cnum);                          $errors = &process_linkprot($cdom,$cnum,$values->{$action},$changes,'course',$lastactref);
                     my (@items,%deletions,%itemids,%haschanges);  
                     if ($env{'form.linkprot_add'}) {  
                         my $name = $env{'form.linkprot_name_add'};  
                         $name =~ s/(`)/'/g;  
                         my ($newid,$error) = &get_courselti_id($cdom,$cnum,$name);  
                         if ($newid) {  
                             $itemids{'add'} = $newid;  
                             push(@items,'add');  
                             $haschanges{$newid} = 1;  
                         } else {  
                             $errors .= '<span class="LC_error">'.  
                                        &mt('Failed to acquire unique ID for link protection').  
                                        '</span>';  
                         }  
                     }  
                     if (ref($values->{$action}) eq 'HASH') {  
                         my @todelete = &Apache::loncommon::get_env_multiple('form.linkprot_del');  
                         my $maxnum = $env{'form.linkprot_maxnum'};  
                         for (my $i=0; $i<=$maxnum; $i++) {  
                             my $itemid = $env{'form.linkprot_id_'.$i};  
                             $itemid =~ s/\D+//g;  
                             if ($itemid) {  
                                 if (ref($values->{$action}->{$itemid}) eq 'HASH') {  
                                     push(@items,$i);  
                                     $itemids{$i} = $itemid;  
                                     if ((@todelete > 0) && (grep(/^$i$/,@todelete))) {  
                                         $deletions{$itemid} = $values->{$action}->{$itemid}->{'name'};  
                                     }  
                                 }  
                             }  
                         }  
                     }  
   
                     foreach my $idx (@items) {  
                         my $itemid = $itemids{$idx};  
                         next unless ($itemid);  
                         if (exists($deletions{$itemid})) {  
                             $lti{$itemid} = $deletions{$itemid};  
                             $haschanges{$itemid} = 1;  
                             next;  
                         }  
                         my %current;  
                         if (ref($values->{$action}) eq 'HASH') {  
                             if (ref($values->{$action}->{$itemid}) eq 'HASH') {  
                                 foreach my $key (keys(%{$values->{$action}->{$itemid}})) {  
                                     $current{$key} = $values->{$action}->{$itemid}->{$key};  
                                 }  
                             }  
                         }  
                         foreach my $inner ('name','lifetime','version') {  
                             my $formitem = 'form.linkprot_'.$inner.'_'.$idx;  
                             $env{$formitem} =~ s/(`)/'/g;  
                             if ($inner eq 'lifetime') {  
                                 $env{$formitem} =~ s/[^\d.]//g;  
                             }  
                             unless ($idx eq 'add') {  
                                 if ($current{$inner} ne $env{$formitem}) {  
                                     $haschanges{$itemid} = 1;  
                                 }  
                             }  
                             if ($env{$formitem} ne '') {  
                                 $lti{$itemid}{$inner} = $env{$formitem};  
                             }  
                         }  
                         unless ($switchserver) {  
                             my $keyitem = 'form.linkprot_key_'.$idx;  
                             $env{$keyitem} =~ s/(`)/'/g;  
                             unless ($idx eq 'add') {  
                                 if ($current{'key'} ne $env{$keyitem}) {  
                                     $haschanges{$itemid} = 1;  
                                 }  
                             }  
                             if ($env{$keyitem} ne '') {  
                                 $lti{$itemid}{'key'} = $env{$keyitem};  
                             }  
                             my $secretitem = 'form.linkprot_secret_'.$idx;  
                             $env{$secretitem} =~ s/(`)/'/g;  
                             if ($current{'usable'}) {  
                                 if ($env{'form.linkprot_changesecret_'.$idx}) {  
                                     if ($env{$secretitem} ne '') {  
                                         $lti{$itemid}{'secret'} = $env{$secretitem};  
                                         $haschanges{$itemid} = 1;  
                                     }  
                                 } else {  
                                     $lti{$itemid}{'secret'} = $current{'secret'};  
                                 }  
                             } elsif ($env{$secretitem} ne '') {  
                                 $lti{$itemid}{'secret'} = $env{$secretitem};  
                                 $haschanges{$itemid} = 1;  
                             }  
                         }  
                     }  
                     if (keys(%haschanges)) {  
                         foreach my $entry (keys(%haschanges)) {  
                             $changes->{$entry} = $lti{$entry};  
                         }  
                     }                      }
                 } else {                  } else {
                     foreach my $entry (@ordered) {                      foreach my $entry (@ordered) {
Line 1570  sub process_changes { Line 1480  sub process_changes {
     return $errors;      return $errors;
 }  }
   
 sub get_courselti_id {  sub process_linkprot {
     my ($cdom,$cnum,$name) = @_;      my ($cdom,$cnum,$values,$changes,$context,$lastactref) = @_;
     # get lock on lti db in course      my ($home,$dest,$ltiauth,$privkey,$privnum,$cipher,$errors,%linkprot);
       if (ref($values) eq 'HASH') {
           foreach my $id (keys(%{$values})) {
               if ($id =~ /^\d+$/) {
                   unless (ref($values->{$id}) eq 'HASH') {
                       $linkprot{$id} = '';
                   }
               }
           }
       }
       my %domdefs = &Apache::lonnet::get_domain_defaults($cdom);
       my @ids=&Apache::lonnet::current_machine_ids();
       if ($context eq 'domain') {
           $home = &Apache::lonnet::domain($cdom,'primary');
       } else {
           $home = &Apache::lonnet::homeserver($cnum,$cdom);
       }
       if ((($context eq 'domain') && ($domdefs{'linkprotenc_dom'})) ||
           (($context eq 'course') && ($domdefs{'linkprotenc_crs'}))) {
           unless (($home eq 'no_host') || ($home eq '')) {
               if (grep(/^\Q$home\E$/,@ids)) {
                   if (ref($domdefs{'privhosts'}) eq 'ARRAY') {
                       if (grep(/^\Q$home\E$/,@{$domdefs{'privhosts'}})) {
                           my %privhash  = &Apache::lonnet::restore_dom('lti','private',$cdom,$home,1);
                           $privkey = $privhash{'key'};
                           $privnum = $privhash{'version'};
                           if (($privnum) && ($privkey ne '')) {
                               $cipher = Crypt::CBC->new({'key'     => $privkey,
                                                          'cipher'  => 'DES'});
                           }
                       }
                   }
               }
           }
       }
       if ($context eq 'domain') {
           $dest = '/adm/domainprefs';
           $ltiauth = 1;
       } else {
           $dest = '/adm/courseprefs';
           if (exists($env{'course.'.$env{'request.course.id'}.'.internal.ltiauth'})) {
               $ltiauth = $env{'course.'.$env{'request.course.id'}.'.internal.ltiauth'};
           } else {
               my %domdefs = &Apache::lonnet::get_domain_defaults($cdom);
               $ltiauth = $domdefs{'crsltiauth'};
           }
       }
       my $switchserver = &check_switchserver($cdom,$cnum,$context,$dest);
       my (@items,%deletions,%itemids,%haschanges);
       if ($env{'form.linkprot_add'}) {
           my $name = $env{'form.linkprot_name_add'};
           $name =~ s/(`)/'/g;
           my ($newid,$error) = &get_linkprot_id($cdom,$cnum,$name,$context);
           if ($newid) {
               $itemids{'add'} = $newid;
               push(@items,'add');
               $haschanges{$newid} = 1;
           } else {
               $errors .= '<span class="LC_error">'.
                          &mt('Failed to acquire unique ID for link protection').
                          '</span>';
           }
       }
       if (ref($values) eq 'HASH') {
           my @todelete = &Apache::loncommon::get_env_multiple('form.linkprot_del');
           my $maxnum = $env{'form.linkprot_maxnum'};
           for (my $i=0; $i<=$maxnum; $i++) {
               my $itemid = $env{'form.linkprot_id_'.$i};
               $itemid =~ s/\D+//g;
               if ($itemid) {
                   if (ref($values->{$itemid}) eq 'HASH') {
                       push(@items,$i);
                       $itemids{$i} = $itemid;
                       if ((@todelete > 0) && (grep(/^$i$/,@todelete))) {
                           $deletions{$itemid} = $values->{$itemid}->{'name'};
                       }
                   }
               }
           }
       }
       foreach my $idx (@items) {
           my $itemid = $itemids{$idx};
           next unless ($itemid);
           if (exists($deletions{$itemid})) {
               $linkprot{$itemid} = $deletions{$itemid};
               $haschanges{$itemid} = 1;
               next;
           }
           my %current;
           if (ref($values) eq 'HASH') {
               if (ref($values->{$itemid}) eq 'HASH') {
                   foreach my $key (keys(%{$values->{$itemid}})) {
                       $current{$key} = $values->{$itemid}->{$key};
                   }
               }
           }
           foreach my $inner ('name','lifetime','version') {
               my $formitem = 'form.linkprot_'.$inner.'_'.$idx;
               $env{$formitem} =~ s/(`)/'/g;
               if ($inner eq 'lifetime') {
                   $env{$formitem} =~ s/[^\d.]//g;
               }
               unless ($idx eq 'add') {
                   if ($current{$inner} ne $env{$formitem}) {
                       $haschanges{$itemid} = 1;
                   }
               }
               if ($env{$formitem} ne '') {
                   $linkprot{$itemid}{$inner} = $env{$formitem};
               }
           }
           if ($ltiauth) {
               my $reqitem = 'form.linkprot_requser_'.$idx;
               $env{$reqitem} =~ s/(`)/'/g;
               unless ($idx eq 'add') {
                   if ((!$current{'requser'} && $env{$reqitem}) ||
                       ($current{'requser'} && !$env{$reqitem})) {
                       $haschanges{$itemid} = 1;
                   }
               }
               if ($env{$reqitem} == 1) {
                   $linkprot{$itemid}{'requser'} = $env{$reqitem};
                   foreach my $inner ('mapuser','notstudent') {
                       my $formitem = 'form.linkprot_'.$inner.'_'.$idx;
                       $env{$formitem} =~ s/(`)/'/g;
                       if ($inner eq 'mapuser') {
                           if ($env{$formitem} eq 'other') {
                               my $mapuser = $env{'form.linkprot_customuser_'.$idx};
                               $mapuser =~ s/(`)/'/g;
                               $mapuser =~ s/^\s+|\s+$//g;
                               if ($mapuser ne '') {
                                   $linkprot{$itemid}{$inner} = $mapuser;
                               } else {
                                   delete($linkprot{$itemid}{'requser'});
                                   last;
                               }
                           } elsif ($env{$formitem} eq 'sourcedid') {
                               $linkprot{$itemid}{$inner} = 'lis_person_sourcedid';
                           } elsif ($env{$formitem} eq 'email') {
                               $linkprot{$itemid}{$inner} = 'lis_person_contact_email_primary';
                           }
                       } else {
                           $linkprot{$itemid}{$inner} = $env{$formitem};
                       }
                       unless ($idx eq 'add') {
                           if ($current{$inner} ne $linkprot{$itemid}{$inner}) {
                               $haschanges{$itemid} = 1;
                           }
                       }
                   }
               }
           }
           unless ($switchserver) {
               my $keyitem = 'form.linkprot_key_'.$idx;
               $env{$keyitem} =~ s/(`)/'/g;
               unless ($idx eq 'add') {
                   if ($current{'key'} ne $env{$keyitem}) {
                       $haschanges{$itemid} = 1;
                   }
               }
               if ($env{$keyitem} ne '') {
                   $linkprot{$itemid}{'key'} = $env{$keyitem};
               }
               my $secretitem = 'form.linkprot_secret_'.$idx;
               $env{$secretitem} =~ s/(`)/'/g;
               if ($current{'usable'}) {
                   if ($env{'form.linkprot_changesecret_'.$idx}) {
                       if ($env{$secretitem} ne '') {
                           if ($privnum && $cipher) {
                               $linkprot{$itemid}{'secret'} = $cipher->encrypt_hex($env{$secretitem});
                               $linkprot{$itemid}{'cipher'} = $privnum;
                           } else {
                               $linkprot{$itemid}{'secret'} = $env{$secretitem};
                           }
                           $haschanges{$itemid} = 1;
                       }
                   } else {
                       $linkprot{$itemid}{'secret'} = $current{'secret'};
                       $linkprot{$itemid}{'cipher'} = $current{'cipher'};
                   }
               } elsif ($env{$secretitem} ne '') {
                   if ($privnum && $cipher) {
                       $linkprot{$itemid}{'secret'} = $cipher->encrypt_hex($env{$secretitem});
                       $linkprot{$itemid}{'cipher'} = $privnum;
                   } else {
                       $linkprot{$itemid}{'secret'} = $env{$secretitem};
                   }
                   $haschanges{$itemid} = 1;
               }
           }
       }
       if (keys(%haschanges)) {
           foreach my $entry (keys(%haschanges)) {
               $changes->{$entry} = $linkprot{$entry};
           }
           if (ref($lastactref) eq 'HASH') {
               $lastactref->{'courselti'} = 1';
           }
       }
       return $errors;
   }
   
   sub get_linkprot_id {
       my ($cdom,$cnum,$name,$context) = @_;
       # get lock on lti db in course or linkprot db in domain
     my $lockhash = {      my $lockhash = {
                       lock => $env{'user.name'}.                        lock => $env{'user.name'}.
                               ':'.$env{'user.domain'},                                ':'.$env{'user.domain'},
                    };                     };
     my $tries = 0;      my $tries = 0;
     my $gotlock = &Apache::lonnet::newput('lti',$lockhash,$cdom,$cnum);      my $gotlock;
       if ($context eq 'domain') {
           $gotlock = &Apache::lonnet::newput_dom('linkprot',$lockhash,$cdom);
       } else {
           $gotlock = &Apache::lonnet::newput('lti',$lockhash,$cdom,$cnum);
       }
     my ($id,$error);      my ($id,$error);
     while (($gotlock ne 'ok') && ($tries<10)) {      while (($gotlock ne 'ok') && ($tries<10)) {
         $tries ++;          $tries ++;
         sleep (0.1);          sleep (0.1);
         $gotlock = &Apache::lonnet::newput('lti',$lockhash,$cdom,$cnum);          if ($context eq 'domain') {
               $gotlock = &Apache::lonnet::newput_dom('linkprot',$lockhash,$cdom); 
           } else {
               $gotlock = &Apache::lonnet::newput('lti',$lockhash,$cdom,$cnum);
           }
     }      }
     if ($gotlock eq 'ok') {      if ($gotlock eq 'ok') {
         my %currids  = &Apache::lonnet::dump('lti',$cdom,$cnum,undef,undef,undef,1);          my %currids;
           if ($context eq 'domain') {
               %currids = &Apache::lonnet::dump_dom('linkprot',$cdom);
           } else {
               %currids  = &Apache::lonnet::dump('lti',$cdom,$cnum,undef,undef,undef,1);
           }
         if ($currids{'lock'}) {          if ($currids{'lock'}) {
             delete($currids{'lock'});              delete($currids{'lock'});
             if (keys(%currids)) {              if (keys(%currids)) {
Line 1600  sub get_courselti_id { Line 1728  sub get_courselti_id {
                 $id = 1;                  $id = 1;
             }              }
             if ($id) {              if ($id) {
                 unless (&Apache::lonnet::newput('lti',{ $id => $name },$cdom,$cnum) eq 'ok') {                  if ($context eq 'domain') {
                     $error = 'nostore';                       unless (&Apache::lonnet::newput_dom('linkprot',{ $id => $name },$cdom) eq 'ok') {
                            $error = 'nostore';
                        }
                   } else {
                       unless (&Apache::lonnet::newput('lti',{ $id => $name },$cdom,$cnum) eq 'ok') {
                           $error = 'nostore';
                       }
                 }                  }
             } else {              } else {
                 $error = 'nonumber';                  $error = 'nonumber';
             }              }
         }          }
         my $dellockoutcome = &Apache::lonnet::del('lti',['lock'],$cdom,$cnum);          my $dellockoutcome; 
           if ($context eq 'domain') {
               $dellockoutcome = &Apache::lonnet::del_dom('linkprot',['lock'],$cdom);
           } else {
               $dellockoutcome = &Apache::lonnet::del('lti',['lock'],$cdom,$cnum);
           }
     } else {      } else {
         $error = 'nolock';          $error = 'nolock';
     }      }
Line 1658  sub store_changes { Line 1797  sub store_changes {
     my ($chome,$output);      my ($chome,$output);
     my (%storehash,@delkeys,@need_env_update,@oldcloner,%oldlinkprot);      my (%storehash,@delkeys,@need_env_update,@oldcloner,%oldlinkprot);
     if ((ref($values) eq 'HASH') && (ref($changes) eq 'HASH')) {      if ((ref($values) eq 'HASH') && (ref($changes) eq 'HASH')) {
         if (ref($values->{'linkprotection'}) eq 'HASH') {          if (ref($values->{'linkprot'}) eq 'HASH') {
             %oldlinkprot = %{$values->{'linkprotection'}};              %oldlinkprot = %{$values->{'linkprot'}};
         }          }
         delete($values->{'linkprotection'});          delete($values->{'linkprot'});
         %storehash = %{$values};          %storehash = %{$values};
     } else {      } else {
         if ($crstype eq 'Community') {          if ($crstype eq 'Community') {
Line 1674  sub store_changes { Line 1813  sub store_changes {
     my ($numchanges,$skipstore);      my ($numchanges,$skipstore);
     if (ref($changes) eq 'HASH') {      if (ref($changes) eq 'HASH') {
         $numchanges = scalar(keys(%{$changes}));          $numchanges = scalar(keys(%{$changes}));
         if (($numchanges == 1) && (exists($changes->{'linkprotection'}))) {          if (($numchanges == 1) && (exists($changes->{'linkprot'}))) {
             $skipstore = 1;              $skipstore = 1;
         } elsif (!$numchanges) {          } elsif (!$numchanges) {
             if ($crstype eq 'Community') {              if ($crstype eq 'Community') {
Line 1710  sub store_changes { Line 1849  sub store_changes {
                                            "'$storehash{$key}'")).'</li>';                                             "'$storehash{$key}'")).'</li>';
                             }                              }
                         }                          }
                     } elsif ($item eq 'linkprotection') {                      } elsif ($item eq 'linkprot') {
                         my (%ltienc,$lti_save_error);                          $output .= &store_linkprot($cdom,$cnum,'course',$changes->{$item},\%oldlinkprot);
                         if (ref($changes->{$item}) eq 'HASH') {  
                             foreach my $id (sort { $a <=> $b } keys(%{$changes->{$item}})) {  
                                 if (ref($changes->{$item}->{$id}) eq 'HASH') {  
                                     if (exists($changes->{$item}->{$id}->{'key'})) {  
                                         $ltienc{$id}{'key'} = $changes->{$item}->{$id}->{'key'};  
                                         delete($changes->{$item}->{$id}->{'key'});  
                                     }  
                                     if (exists($changes->{$item}->{$id}->{'secret'})) {  
                                         $ltienc{$id}{'secret'} = $changes->{$item}->{$id}->{'secret'};  
                                         delete($changes->{$item}->{$id}->{'secret'});  
                                     } elsif (ref($oldlinkprot{$id}) eq 'HASH') {  
                                         if (exists($oldlinkprot{$id}{'usable'})) {  
                                             $changes->{$item}->{$id}->{'usable'} = 1;  
                                         }  
                                     }  
                                 }  
                             }  
                         }  
                         if (keys(%ltienc) > 0) {  
                             if (&Apache::lonnet::put('nohist_ltienc',\%ltienc,$cdom,$cnum,1) eq 'ok') {  
                                 foreach my $id (keys(%ltienc)) {  
                                     if (exists($ltienc{$id}{'secret'})) {  
                                         $changes->{$item}->{$id}->{'usable'} = 1;  
                                     }  
                                 }  
                             } else {  
                                 $lti_save_error = 1;  
                             }  
                         }  
                         unless ($lti_save_error) {  
                             if (&Apache::lonnet::put('lti',$changes->{$item},$cdom,$cnum,1) eq 'ok') {  
                                 my $hashid=$cdom.'_'.$cnum;  
                                 &Apache::lonnet::devalidate_cache_new('courselti',$hashid);  
                                 $chome = &Apache::lonnet::homeserver($cnum,$cdom);  
                                 unless (($chome eq 'no_host') || ($chome eq '')) {  
                                     my @ids=&Apache::lonnet::current_machine_ids();  
                                     unless (grep(/^\Q$chome\E$/,@ids)) {  
                                         &Apache::lonnet::devalidate_cache_new('courseltienc',$hashid);  
                                     }  
                                 }  
                                 foreach my $id (sort { $a <=> $b } %{$changes->{$item}}) {  
                                     if (ref($changes->{$item}->{$id}) eq 'HASH') {  
                                         my %values = %{$changes->{$item}->{$id}};  
                                         my %desc = &linkprot_names();  
                                         my $display;  
                                         foreach my $title ('name','lifetime','version','key','secret') {  
                                             if (($title eq 'key') || ($title eq 'secret')) {  
                                                 if (ref($ltienc{$id}) eq 'HASH') {  
                                                     if (exists($ltienc{$id}{$title})) {  
                                                         if ($title eq 'secret') {  
                                                             my $length = length($ltienc{$id}{$title});  
                                                             $display .= $desc{$title}.': '.('*' x $length);  
                                                         } else {  
                                                             $display .= $desc{$title}.': '.$ltienc{$id}{$title}.', ';  
                                                         }  
                                                     }  
                                                 }  
                                             } elsif ($title eq 'version') {  
                                                 if ($values{$title} eq 'LTI-1p0') {  
                                                     $display .= $desc{$title}.': 1.1, ';  
                                                 }  
                                             } else {  
                                                 $display .= $desc{$title}.': '.$values{$title}.', ';  
                                             }  
                                         }  
                                         $display =~ s/, $//;  
                                         $output .= '<li>'.&Apache::lonhtmlcommon::confirm_success(&mt('[_1] set to [_2]','<i>'.$id.'</i>',  
                                                    "'$display'")).'</li>';  
                                     } elsif (ref($oldlinkprot{$id}) eq 'HASH') {  
                                         my $oldname = $oldlinkprot{$id}{'name'};  
                                         $output .= '<li>'.&Apache::lonhtmlcommon::confirm_success(&mt('Deleted setting for [_1]','<i>'."$id ($oldname)".'</i>')).'</li>';  
                                     }  
                                 }  
                             } else {  
                                 $lti_save_error = 1;  
                             }  
                         }  
                         unless ($lti_save_error) {  
                             my @deletions;  
                             foreach my $id (sort { $a <=> $b } keys(%{$changes->{$item}})) {  
                                 unless (ref($changes->{$item}->{$id}) eq 'HASH') {  
                                     push (@deletions,$id);  
                                 }  
                             }  
                             if (@deletions) {  
                                 &Apache::lonnet::del('nohist_ltienc',\@deletions,$cdom,$cnum);  
                             }  
                         }  
                         if ($lti_save_error) {  
                             $output .= '<li>'.  
                                        '<span class="LC_error">'.  
                                        &mt('An error occurred when saving changes to link protection settings, which remain unchanged.').  
                                        '</span>'.  
                                        '</li>';  
                         }  
                     } else {                      } else {
                         if (ref($prefs->{$item}->{'ordered'}) eq 'ARRAY') {                          if (ref($prefs->{$item}->{'ordered'}) eq 'ARRAY') {
                             my @settings = @{$prefs->{$item}->{'ordered'}};                              my @settings = @{$prefs->{$item}->{'ordered'}};
Line 2140  sub store_changes { Line 2184  sub store_changes {
     return $output;      return $output;
 }  }
   
   sub store_linkprot {
       my ($cdom,$cnum,$context,$changes,$oldlinkprot) = @_;
       my ($ltiauth,$home,$lti_save_error,$output,$error,%ltienc,@deletions);
       if ($context eq 'domain') {
           $ltiauth = 1;
           $home = &Apache::lonnet::domain($cdom,'primary');
       } else {
           $home = &Apache::lonnet::homeserver($cnum,$cdom);
           if (exists($env{'course.'.$env{'request.course.id'}.'.internal.ltiauth'})) {
               $ltiauth = $env{'course.'.$env{'request.course.id'}.'.internal.ltiauth'};
           } else {
               my %domdefs = &Apache::lonnet::get_domain_defaults($cdom);
               $ltiauth = $domdefs{'crsltiauth'};
           }
       }
       if (ref($changes) eq 'HASH') {
           foreach my $id (sort { $a <=> $b } keys(%{$changes})) {
               if (ref($changes->{$id}) eq 'HASH') {
                   if (exists($changes->{$id}->{'key'})) {
                       $ltienc{$id}{'key'} = $changes->{$id}->{'key'};
                       delete($changes->{$id}->{'key'});
                   }
                   if (exists($changes->{$id}->{'secret'})) {
                       $ltienc{$id}{'secret'} = $changes->{$id}->{'secret'};
                       delete($changes->{$id}->{'secret'});
                   } elsif (ref($oldlinkprot->{$id}) eq 'HASH') {
                       if (exists($oldlinkprot->{$id}{'usable'})) {
                           $changes->{$id}->{'usable'} = 1;
                       }
                   }
               }
           }
       }
       my @ids=&Apache::lonnet::current_machine_ids();
       if (keys(%ltienc) > 0) {
           if ($context eq 'domain') {
               foreach my $id (keys(%ltienc)) {
                   if (exists($ltienc{$id}{'secret'})) {
                       $changes->{$id}->{'usable'} = 1;
                   }
               }
           } else {
               unless (($home eq 'no_host') || ($home eq '')) {
                   my $allowed;
                   foreach my $id (@ids) { if ($id eq $home) { $allowed=1; } }
                   if ($allowed) {
                       if (&Apache::lonnet::put('nohist_ltienc',\%ltienc,$cdom,$cnum,1) eq 'ok') {
                           foreach my $id (keys(%ltienc)) {
                               if (exists($ltienc{$id}{'secret'})) {
                                   $changes->{$id}->{'usable'} = 1;
                               }
                           }
                       } else {
                           $lti_save_error = 1;
                       }
                   }
               }
           }
       }
       unless ($lti_save_error) {
           if ($context eq 'course') {
               if (&Apache::lonnet::put('lti',$changes,$cdom,$cnum,1) eq 'ok') {
                   my $hashid=$cdom.'_'.$cnum;
                   &Apache::lonnet::devalidate_cache_new('courselti',$hashid);
                   unless (($home eq 'no_host') || ($home eq '')) {
                       if (grep(/^\Q$home\E$/,@ids)) {
                           &Apache::lonnet::devalidate_cache_new('courseltienc',$hashid);
                       }
                   }
               } else {
                   $lti_save_error = 1;
               }
           }
           unless ($lti_save_error) {
               foreach my $id (sort { $a <=> $b } %{$changes}) {
                   if (ref($changes->{$id}) eq 'HASH') {
                       my %values = %{$changes->{$id}};
                       my %desc = &linkprot_names();
                       my $display;
                       foreach my $title ('name','lifetime','version','key','secret') {
                           if (($title eq 'key') || ($title eq 'secret')) {
                               if (ref($ltienc{$id}) eq 'HASH') {
                                   if (exists($ltienc{$id}{$title})) {
                                       if ($title eq 'secret') {
                                           my $length = length($ltienc{$id}{$title});
                                           $display .= $desc{$title}.': ['.&mt('not shown').'], ';
                                       } else {
                                           $display .= $desc{$title}.': '.$ltienc{$id}{$title}.', ';
                                       }
                                   }
                               }
                           } elsif ($title eq 'version') {
                               if ($values{$title} eq 'LTI-1p0') {
                                   $display .= $desc{$title}.': 1.1, ';
                               }
                           } else {
                               $display .= $desc{$title}.': '.$values{$title}.', ';
                           }
                       }
                       if ($ltiauth) {
                           if (($values{'requser'}) && ($values{'mapuser'} ne '')) {
                               if ($values{'mapuser'} eq 'lis_person_contact_email_primary') {
                                   $display .= &mt('Source of username: Email address [_1]',
                                                   '(lis_person_contact_email_primary)').', ';
                               } elsif ($values{'mapuser'} eq 'lis_person_sourcedid') {
                                   $display .= &mt('Source of username: User ID [_1]',
                                                   '(lis_person_sourcedid)').', ';
                               } else {
                                   $display .= &mt('Source of username: [_1]',$values{'mapuser'}).', ';
                               }
                               if ($values{'notstudent'} eq 'auth') {
                                   $display .= &mt('Display LON-CAPA login page if no match').', ';
                               } elsif ($values{'notstudent'} eq 'reject') {
                                   $display .= &mt('Discontinue launch if no match').', ';
                               }
                           }
                       }
                       $display =~ s/, $//;
                       $output .= '<li>'.&Apache::lonhtmlcommon::confirm_success(&mt('[_1] set to [_2]','<i>'.$id.'</i>',
                                                                                 "'$display'")).'</li>';
                   } elsif (ref($oldlinkprot->{$id}) eq 'HASH') {
                       my $oldname = $oldlinkprot->{$id}{'name'};
                       $output .= '<li>'.&Apache::lonhtmlcommon::confirm_success(&mt('Deleted setting for [_1]','<i>'."$id ($oldname)".'</i>')).'</li>';
                   }
               }
           } else {
               $lti_save_error = 1;
           }
       }
       unless ($lti_save_error) {
           foreach my $id (sort { $a <=> $b } keys(%{$changes})) {
               unless (ref($changes->{$id}) eq 'HASH') {
                   push(@deletions,$id);
               }
           }
           if (@deletions) {
               if ($context eq 'course') {
                   &Apache::lonnet::del('nohist_ltienc',\@deletions,$cdom,$cnum);
               }
           }
       }
       if ($lti_save_error) {
           $output .= '<li>'.
                      '<span class="LC_error">'.
                      &mt('An error occurred when saving changes to link protection settings, which remain unchanged.').
                      '</span>'.
                      '</li>';
       }
       return $output;
   }
   
 sub update_env {  sub update_env {
     my ($cnum,$cdom,$chome,$need_env_update,$storehash)  = @_;      my ($cnum,$cdom,$chome,$need_env_update,$storehash)  = @_;
     my $count = 0;      my $count = 0;
Line 2479  function toggleAddmenucoll() { Line 2674  function toggleAddmenucoll() {
 }  }
 ENDSCRIPT  ENDSCRIPT
     }      }
     my $linkprotector_js = <<"ENDSCRIPT";  
 function toggleLTI(form,num,item) {  
     var radioname = '';  
     var currdivid = '';  
     var newdivid = '';  
     if ((document.getElementById('linkprot_divcurr'+item+'_'+num)) &&  
         (document.getElementById('linkprot_divchg'+item+'_'+num))) {  
         currdivid = document.getElementById('linkprot_divcurr'+item+'_'+num);  
         newdivid = document.getElementById('linkprot_divchg'+item+'_'+num);  
         radioname = form.elements['linkprot_change'+item+'_'+num];  
         if (radioname) {  
             if (radioname.length > 0) {  
                 var setvis;  
                 for (var i=0; i<radioname.length; i++) {  
                     if (radioname[i].checked == true) {  
                         if (radioname[i].value == 1) {  
                             newdivid.style.display = 'inline-block';  
                             currdivid.style.display = 'none';  
                             setvis = 1;  
                         }  
                         break;  
                     }  
                 }  
                 if (!setvis) {  
                     newdivid.style.display = 'none';  
                     currdivid.style.display = 'inline-block';  
                 }  
             }  
         }  
     }  
     return;  
 }  
 ENDSCRIPT  
     $jscript = '<script type="text/javascript" language="Javascript">'."\n".      $jscript = '<script type="text/javascript" language="Javascript">'."\n".
                '// <![CDATA['."\n".                   '// <![CDATA['."\n".  
                $browse_js."\n".$categorize_js."\n".$loncaparev_js."\n".                 $browse_js."\n".$categorize_js."\n".$loncaparev_js."\n".
                $cloners_js."\n".$instcode_js.                 $cloners_js."\n".$instcode_js.
                $syllabus_js."\n".$menuitems_js."\n".                 $syllabus_js."\n".$menuitems_js."\n".
                $linkprotector_js."\n".'//]]>'."\n".                 &linkprot_javascript()."\n".'//]]>'."\n".
                '</script>'."\n".$stubrowse_js."\n";                 '</script>'."\n".$stubrowse_js."\n";
     return $jscript;      return $jscript;
 }  }
Line 2603  function getIndexByName(item) { Line 2765  function getIndexByName(item) {
 ENDSCRIPT  ENDSCRIPT
 }  }
   
   sub linkprot_javascript {
       return <<"ENDSCRIPT";
   function toggleLinkProt(form,num,item) {
       var radioname = '';
       var currdivid = '';
       var newdivid = '';
       if ((document.getElementById('linkprot_divcurr'+item+'_'+num)) &&
           (document.getElementById('linkprot_divchg'+item+'_'+num))) {
           currdivid = document.getElementById('linkprot_divcurr'+item+'_'+num);
           newdivid = document.getElementById('linkprot_divchg'+item+'_'+num);
           radioname = form.elements['linkprot_change'+item+'_'+num];
           if (radioname) {
               if (radioname.length > 0) {
                   var setvis;
                   for (var i=0; i<radioname.length; i++) {
                       if (radioname[i].checked == true) {
                           if (radioname[i].value == 1) {
                               newdivid.style.display = 'inline-block';
                               currdivid.style.display = 'none';
                               setvis = 1;
                           }
                           break;
                       }
                   }
                   if (!setvis) {
                       newdivid.style.display = 'none';
                       currdivid.style.display = 'inline-block';
                   }
               }
           }
       }
       return;
   }
   
   function toggleLinkProtReqUser(form,item,extra,valon,styleon,num) {
       if (document.getElementById('linkprot_'+extra+'_'+num)) {
           var extraid = document.getElementById('linkprot_'+extra+'_'+num);
           var itemname = form.elements['linkprot_'+item+'_'+num];
           if (itemname) {
               if (itemname.length > 0) {
                   var setvis;
                   for (var i=0; i<itemname.length; i++) {
                       if (itemname[i].checked == true) {
                           if (itemname[i].value == valon) {
                               extraid.style.display = styleon;
                               setvis = 1;
                           }
                           break;
                       }
                   }
                   if (!setvis) {
                       extraid.style.display = 'none';
                   }
               }
           }
       }
       return;
   }
   
   function uncheckLinkProtMakeVis(item,num) {
       if (document.getElementById('linkprot_'+item+'_'+num)) {
           var currtype = document.getElementById('linkprot_'+item+'_'+num).type;
           if (currtype.toLowerCase() == 'checkbox') {
               document.getElementById('linkprot_'+item+'_'+num).checked = false;
           }
       }
       return;
   }
   ENDSCRIPT
   
   }
   
   
 sub print_courseinfo {  sub print_courseinfo {
     my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype,$noedit) = @_;      my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype,$noedit) = @_;
Line 5406  sub menucollections_display { Line 5640  sub menucollections_display {
 }  }
   
 sub print_linkprotection {  sub print_linkprotection {
     my ($cdom,$cnum,$settings,$rowtotal,$crstype,$noedit) = @_;      my ($cdom,$cnum,$settings,$rowtotal,$crstype,$noedit,$context) = @_;
     unless (ref($settings) eq 'HASH') {  
         return;  
     }  
   
     my %linkprotection;      my %linkprotection;
     my $count = 0;      my $count = 0;
     my $next = 1;      my $next = 1;
     my ($datatable,$disabled,$css_class);      my ($datatable,$disabled,$css_class,$dest);
     if ($noedit) {      if ($noedit) {
         $disabled = ' disabled="disabled"';          $disabled = ' disabled="disabled"';
     }      }
     my %lt = &linkprot_names();      my %desc = &linkprot_names();
       my %lt = &Apache::lonlocal::texthash (
          'requ'      => 'Required settings',
          'opti'      => 'Optional settings',
       );
     my $itemcount = 0;      my $itemcount = 0;
   
     my $switchserver = &check_switchserver($cdom,$cnum);      my $ltiauth;
       if ($context eq 'domain') {
           $ltiauth = 1;
       } else {
           if (exists($env{'course.'.$env{'request.course.id'}.'.internal.ltiauth'})) {
               $ltiauth = $env{'course.'.$env{'request.course.id'}.'.internal.ltiauth'};
           } else {
               my %domdefs = &Apache::lonnet::get_domain_defaults($cdom);
               $ltiauth = $domdefs{'crsltiauth'};
           }
       }
       if ($context eq 'domain') {
           $dest = '/adm/domainprefs';
       } else {
           $dest = '/adm/courseprefs';
       }
       
       my ($switchserver,$switchmessage);
       $switchserver = &check_switchserver($cdom,$cnum,$context,$dest);
       if ($switchserver) {
           if ($context eq 'domain') {
               $switchmessage = &mt("submit from domain's primary library server: [_1].",$switchserver);  
           } elsif ($crstype eq 'Community') {
              $switchmessage = &mt("submit from community's home server: [_1].",$switchserver);
           } else {
               $switchmessage = &mt("submit from course's home server: [_1].",$switchserver);
           }
       }
   
     if (ref($settings->{'linkprotection'}) eq 'HASH') {      if ((ref($settings) eq 'HASH') && (ref($settings->{'linkprot'}) eq 'HASH')) {
         if (keys(%{$settings->{'linkprotection'}})) {          if (keys(%{$settings->{'linkprot'}})) {
             my @current = sort { $a <=> $b } keys(%{$settings->{'linkprotection'}});              my @current = sort { $a <=> $b } keys(%{$settings->{'linkprot'}});
             $next += $current[-1];              $next += $current[-1];
             for (my $i=0; $i<@current; $i++) {              for (my $i=0; $i<@current; $i++) {
                 my $num = $current[$i];                  my $num = $current[$i];
                 my %values;                  my %values;
                 if (ref($settings->{'linkprotection'}->{$num}) eq 'HASH') {                  if (ref($settings->{'linkprot'}->{$num}) eq 'HASH') {
                     %values = %{$settings->{'linkprotection'}->{$num}};                      %values = %{$settings->{'linkprot'}->{$num}};
                 } else {                  } else {
                     next;                      next;
                 }                  }
Line 5443  sub print_linkprotection { Line 5705  sub print_linkprotection {
                 $datatable .=                  $datatable .=
                     '<tr '.$css_class.'><td><span class="LC_nobreak">'.                      '<tr '.$css_class.'><td><span class="LC_nobreak">'.
                     '<label><input type="checkbox" name="linkprot_del" value="'.$i.'"'.$disabled.' />'.                      '<label><input type="checkbox" name="linkprot_del" value="'.$i.'"'.$disabled.' />'.
                     &mt('Delete?').'</label></span></td>'.                      &mt('Delete?').'</label></span></td><td>';
                     '<td><span class="LC_nobreak">'.$lt{'name'}.                  my ($usersty,$onclickrequser,%checkedrequser);
                   if ($ltiauth) {
                       $usersty = 'display:none';
                       $onclickrequser = ' onclick="toggleLinkProtReqUser(this.form,'."'requser','optional','1','block','$i'".');"';
                       %checkedrequser = (
                           no => ' checked="checked"',
                           yes  => '',
                       );
                       if ($values{'requser'}) {
                           $checkedrequser{'yes'} = $checkedrequser{'no'};
                           $checkedrequser{'no'} = '';
                       }
                       $datatable .= '<fieldset><legend>'.$lt{'requ'}.'</legend>';
                       if ($values{'requser'}) { 
                           $usersty = 'display:inline-block';
                       }
                   }
                   $datatable .=
                       '<span class="LC_nobreak">'.$desc{'name'}.
                     ':<input type="text" size="15" name="linkprot_name_'.$i.'" value="'.$values{'name'}.'" autocomplete="off"'.$disabled.' /></span> '.                      ':<input type="text" size="15" name="linkprot_name_'.$i.'" value="'.$values{'name'}.'" autocomplete="off"'.$disabled.' /></span> '.
                     ('&nbsp;'x2).                      ('&nbsp;'x2).
                     '<span class="LC_nobreak">'.$lt{'version'}.':<select name="linkprot_version_'.$i.'"'.$disabled.'>'.                      '<span class="LC_nobreak">'.$desc{'version'}.':<select name="linkprot_version_'.$i.'"'.$disabled.'>'.
                     '<option value="LTI-1p0" '.$selected.'>1.1</option></select></span> '."\n".                      '<option value="LTI-1p0" '.$selected.'>1.1</option></select></span> '."\n".
                     ('&nbsp;'x2).                      ('&nbsp;'x2).
                     '<span class="LC_nobreak">'.$lt{'lifetime'}.':<input type="text" name="linkprot_lifetime_'.$i.'"'.                      '<span class="LC_nobreak">'.$desc{'lifetime'}.':<input type="text" name="linkprot_lifetime_'.$i.'"'.
                     'value="'.$values{'lifetime'}.'" size="3"'.$disabled.' /></span>'.                      ' value="'.$values{'lifetime'}.'" size="3"'.$disabled.' /></span>';
                     '<br /><br />';                  if ($ltiauth) {
                       $datatable .= ('&nbsp;'x2).'<span class="LC_nobreak">'.$desc{'requser'}.'?'.
                                     '<label><input type="radio" name="linkprot_requser_'.$i.'" value="0"'.
                                     $onclickrequser.$checkedrequser{'no'}.$disabled.' />'.&mt('No').'</label>&nbsp;'.
                                     '<label><input type="radio" name="linkprot_requser_'.$i.'" value="1"'.
                                     $onclickrequser.$checkedrequser{'yes'}.$disabled.' />'.&mt('Yes').'</label></span>';
                   }
                   $datatable .= '<br /><br />';
                 if ($values{'key'} ne '') {                  if ($values{'key'} ne '') {
                     $datatable .= '<span class="LC_nobreak">'.$lt{'key'};                      $datatable .= '<span class="LC_nobreak">'.$desc{'key'};
                     if ($noedit) {                      if ($noedit) {
                         $datatable .= ': ['.&mt('not shown').']';                          $datatable .= ': ['.&mt('not shown').']';
                     } elsif ($switchserver) {                      } elsif ($switchserver) {
Line 5464  sub print_linkprotection { Line 5751  sub print_linkprotection {
                     }                      }
                     $datatable .= '</span> '.('&nbsp;'x2);                      $datatable .= '</span> '.('&nbsp;'x2);
                 } elsif (!$switchserver) {                  } elsif (!$switchserver) {
                     $datatable .= '<span class="LC_nobreak">'.$lt{'key'}.':'.                      $datatable .= '<span class="LC_nobreak">'.$desc{'key'}.':'.
                                   '<input type="text" size="25" name="linkprot_key_'.$i.'" value="'.$values{'key'}.'" autocomplete="off"'.$disabled.' />'.                                    '<input type="text" size="25" name="linkprot_key_'.$i.'" value="'.$values{'key'}.'" autocomplete="off"'.$disabled.' />'.
                                   '</span> '.('&nbsp;'x2);                                    '</span> '.('&nbsp;'x2);
                 }                  }
                 if ($switchserver) {                  if ($switchserver) {
                     if ($values{'usable'} ne '') {                      if ($values{'usable'} ne '') {
                         $datatable .= '<div id="linkprot_divcurrsecret_'.$i.'" style="display:inline-block" /><span class="LC_nobreak">'.                          $datatable .= '<div id="linkprot_divcurrsecret_'.$i.'" style="display:inline-block" /><span class="LC_nobreak">'.
                                       $lt{'secret'}.': ['.&mt('not shown').'] '.('&nbsp;'x2).'</span></div>'.                                        $desc{'secret'}.': ['.&mt('not shown').'] '.('&nbsp;'x2).'</span></div>'.
                                       '<span class="LC_nobreak">'.&mt('Change secret?').                                        '<span class="LC_nobreak">'.&mt('Change secret?').
                                       '<label><input type="radio" value="0" name="linkprot_changesecret_'.$i.'" onclick="javascript:toggleLTI(this.form,'."'$i','secret'".');" checked="checked"'.$disabled.' />'.&mt('No').'</label>'.                                        '<label><input type="radio" value="0" name="linkprot_changesecret_'.$i.'" onclick="javascript:toggleLinkProt(this.form,'."'$i','secret'".');" checked="checked"'.$disabled.' />'.&mt('No').'</label>'.
                                       ('&nbsp;'x2).                                        ('&nbsp;'x2).
                                       '<label><input type="radio" value="1" name="linkprot_changesecret_'.$i.'" onclick="javascript:toggleLTI(this.form,'."'$i','secret'".');" '.$disabled.' />'.&mt('Yes').'</label>'.('&nbsp;'x2).                                        '<label><input type="radio" value="1" name="linkprot_changesecret_'.$i.'" onclick="javascript:toggleLinkProt(this.form,'."'$i','secret'".');" '.$disabled.' />'.&mt('Yes').'</label>'.('&nbsp;'x2).
                                       '</span><div id="linkprot_divchgsecret_'.$i.'" style="display:none" />'.                                        '</span><div id="linkprot_divchgsecret_'.$i.'" style="display:none" />'.
                                       '<span class="LC_nobreak"> - '.&mt("submit from course's home server: [_1].",$switchserver).'</span>'.                                        '<span class="LC_nobreak"> - '.$switchmessage.'</span>'.
                                       '</div>';                                        '</div>';
                     } elsif ($values{'key'} eq '') {                      } elsif ($values{'key'} eq '') {
                         $datatable .= '<span class="LC_nobreak">'.&mt('Key and Secret are required').' - '.&mt("submit from course's home server: [_1].",$switchserver).'</span>'."\n";                          $datatable .= '<span class="LC_nobreak">'.&mt('Key and Secret are required').' - '.$switchmessage.'</span>'."\n";
                     } else {                      } else {
                         $datatable .= '<span class="LC_nobreak">'.&mt('Secret required').' - '.&mt("submit from course's home server: [_1].",$switchserver).'</span>'."\n";                          $datatable .= '<span class="LC_nobreak">'.&mt('Secret required').' - '.$switchmessage.'</span>'."\n";
                     }                      }
                 } else {                  } else {
                     if ($values{'usable'} ne '') {                      if ($values{'usable'} ne '') {
                         $datatable .= '<div id="linkprot_divcurrsecret_'.$i.'" style="display:inline-block" /><span class="LC_nobreak">'.                          $datatable .= '<div id="linkprot_divcurrsecret_'.$i.'" style="display:inline-block" /><span class="LC_nobreak">'.
                                       $lt{'secret'}.': ['.&mt('not shown').'] '.('&nbsp;'x2).'</span></div>'.                                        $desc{'secret'}.': ['.&mt('not shown').'] '.('&nbsp;'x2).'</span></div>'.
                                       '<span class="LC_nobreak">'.&mt('Change?').                                        '<span class="LC_nobreak">'.&mt('Change?').
                                       '<label><input type="radio" value="0" name="linkprot_changesecret_'.$i.'" onclick="javascript:toggleLTI(this.form,'."'$i','secret'".');" checked="checked"'.$disabled.' />'.&mt('No').'</label>'.                                        '<label><input type="radio" value="0" name="linkprot_changesecret_'.$i.'" onclick="javascript:toggleLinkProt(this.form,'."'$i','secret'".');" checked="checked"'.$disabled.' />'.&mt('No').'</label>'.
                                       ('&nbsp;'x2).                                        ('&nbsp;'x2).
                                       '<label><input type="radio" value="1" name="linkprot_changesecret_'.$i.'" onclick="javascript:toggleLTI(this.form,'."'$i','secret'".');"'.$disabled.' />'.&mt('Yes').                                        '<label><input type="radio" value="1" name="linkprot_changesecret_'.$i.'" onclick="javascript:toggleLinkProt(this.form,'."'$i','secret'".');"'.$disabled.' />'.&mt('Yes').
                                       '</label>&nbsp;&nbsp;</span><div id="linkprot_divchgsecret_'.$i.'" style="display:none" />'.                                        '</label>&nbsp;&nbsp;</span><div id="linkprot_divchgsecret_'.$i.'" style="display:none" />'.
                                       '<span class="LC_nobreak">'.&mt('New Secret').':'.                                        '<span class="LC_nobreak">'.&mt('New Secret').':'.
                                       '<input type="password" size="20" name="linkprot_secret_'.$i.'" value="" autocomplete="off"'.$disabled.' />'.                                        '<input type="password" size="20" name="linkprot_secret_'.$i.'" value="" autocomplete="off"'.$disabled.' />'.
                                       '<label><input type="checkbox" name="visible" onclick="if (this.checked) { this.form.linkprot_secret_'.$i.'.type='."'text'".' } else { this.form.linkprot_secret_'.$i.'.type='."'password'".' }"'.$disabled.' />'.&mt('Visible input').'</label>'.                                        '<label><input type="checkbox" name="linkprot_visible_'.$i.'" id="linkprot_visible_'.$i.'" onclick="if (this.checked) { this.form.linkprot_secret_'.$i.'.type='."'text'".' } else { this.form.linkprot_secret_'.$i.'.type='."'password'".' }"'.$disabled.' />'.&mt('Visible input').'</label>'.
                                       '<input type="hidden" name="linkprot_id_'.$i.'" value="'.$num.'" /></span></div>';                                        '<input type="hidden" name="linkprot_id_'.$i.'" value="'.$num.'" /></span></div>';
                     } else {                      } else {
                         $datatable .=                          $datatable .=
                             '<span class="LC_nobreak">'.$lt{'secret'}.':'.                              '<span class="LC_nobreak">'.$desc{'secret'}.':'.
                             '<input type="password" size="20" name="linkprot_secret_'.$i.'" value="" autocomplete="off"'.$disabled.' />'.                              '<input type="password" size="20" name="linkprot_secret_'.$i.'" value="" autocomplete="off"'.$disabled.' />'.
                             '<label><input type="checkbox" name="visible" onclick="if (this.checked) { this.form.linkprot_secret_'.$i.'.type='."'text'".' } else { this.form.linkprot_secret_'.$i.'.type='."'password'".' }"'.$disabled.' />'.&mt('Visible input').'</label>'.                              '<label><input type="checkbox" name="linkprot_visible_'.$i.'" id="linkprot_visible_'.$i.'" onclick="if (this.checked) { this.form.linkprot_secret_'.$i.'.type='."'text'".' } else { this.form.linkprot_secret_'.$i.'.type='."'password'".' }"'.$disabled.' />'.&mt('Visible input').'</label>'.
                             '<input type="hidden" name="linkprot_id_'.$i.'" value="'.$num.'" /></span>';                              '<input type="hidden" name="linkprot_id_'.$i.'" value="'.$num.'" /></span>';
                     }                      }
                 }                  }
                   if ($ltiauth) {
                       $datatable .= 
                           '</fieldset>'.
                           '<fieldset id="linkprot_optional_'.$i.'" style="'.$usersty.'"><legend>'.$lt{'opti'}.'</legend>'.
                           &linkprot_options($i,$itemcount,$disabled,\%values,\%desc).
                           '</fieldset>';
                   }
                 $datatable .= '</td></tr>';                  $datatable .= '</td></tr>';
                 $itemcount ++;                  $itemcount ++;
             }              }
Line 5514  sub print_linkprotection { Line 5808  sub print_linkprotection {
     $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'."\n".      $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'."\n".
                   '<input type="hidden" name="linkprot_maxnum" value="'.$next.'" />'."\n".                    '<input type="hidden" name="linkprot_maxnum" value="'.$next.'" />'."\n".
                   '<input type="checkbox" name="linkprot_add" value="1"'.$disabled.' />'.&mt('Add').'</span></td>'."\n".                    '<input type="checkbox" name="linkprot_add" value="1"'.$disabled.' />'.&mt('Add').'</span></td>'."\n".
                   '<td>'.                    '<td width="100%">';
                   '<span class="LC_nobreak">'.$lt{'name'}.      my ($usersty,$onclickrequser,%checkedrequser);
       if ($ltiauth) {
           $usersty = 'display:none';
           $onclickrequser = ' onclick="toggleLinkProtReqUser(this.form,'."'requser','optional','1','block','add'".');"';
           %checkedrequser = (
               no => ' checked="checked"',
               yes  => '',
           );
           $datatable .= '<fieldset><legend>'.$lt{'requ'}.'</legend>';
       }
       $datatable .= '<span class="LC_nobreak">'.$desc{'name'}.
                   ':<input type="text" size="15" name="linkprot_name_add" value="" autocomplete="off"'.$disabled.' /></span> '."\n".                    ':<input type="text" size="15" name="linkprot_name_add" value="" autocomplete="off"'.$disabled.' /></span> '."\n".
                   ('&nbsp;'x2).                    ('&nbsp;'x2).
                   '<span class="LC_nobreak">'.$lt{'version'}.':<select name="linkprot_version_add"'.$disabled.'>'.                    '<span class="LC_nobreak">'.$desc{'version'}.':<select name="linkprot_version_add"'.$disabled.'>'.
                   '<option value="LTI-1p0" selected="selected">1.1</option></select></span> '."\n".                    '<option value="LTI-1p0" selected="selected">1.1</option></select></span> '."\n".
                   ('&nbsp;'x2).                    ('&nbsp;'x2).
                   '<span class="LC_nobreak">'.$lt{'lifetime'}.':<input type="text" size="3" name="linkprot_lifetime_add" value="300"'.$disabled.' /></span> '."\n".                    '<span class="LC_nobreak">'.$desc{'lifetime'}.':<input type="text" size="3" name="linkprot_lifetime_add" value="300"'.$disabled.' /></span> '."\n";
                   '<br /><br />';      if ($ltiauth) {
           $datatable .= ('&nbsp;'x2).'<span class="LC_nobreak">'.$desc{'requser'}.'?'.
                         '<label><input type="radio" name="linkprot_requser_add" value="0"'.
                         $onclickrequser.$checkedrequser{'no'}.$disabled.' />'.&mt('No').'</label>&nbsp;'.
                         '<label><input type="radio" name="linkprot_requser_add" value="1"'.
                         $onclickrequser.$checkedrequser{'yes'}.$disabled.' />'.&mt('Yes').'</label></span>';
       }
       $datatable .= '<br /><br />';
     if ($switchserver) {      if ($switchserver) {
         $datatable .= '<span class="LC_nobreak">'.&mt('Key and Secret are required').' - '.&mt("submit from course's home server: [_1].",$switchserver).'</span>'."\n";          $datatable .= '<span class="LC_nobreak">'.&mt('Key and Secret are required').' - '.$switchmessage.'</span>'."\n";
     } else {      } else {
         $datatable .= '<span class="LC_nobreak">'.$lt{'key'}.':<input type="text" size="25" name="linkprot_key_add" value="" autocomplete="off"'.$disabled.' /></span> '."\n".          $datatable .= '<span class="LC_nobreak">'.$desc{'key'}.':<input type="text" size="25" name="linkprot_key_add" value="" autocomplete="off"'.$disabled.' /></span> '."\n".
                       ('&nbsp;'x2).                        ('&nbsp;'x2).
                       '<span class="LC_nobreak">'.$lt{'secret'}.':<input type="password" size="20" name="linkprot_secret_add" value="" autocomplete="off"'.$disabled.' />'.                        '<span class="LC_nobreak">'.$desc{'secret'}.':<input type="password" size="20" name="linkprot_secret_add" value="" autocomplete="off"'.$disabled.' />'.
                       '<label><input type="checkbox" name="visible" onclick="if (this.checked) { this.form.linkprot_secret_add.type='."'text'".' } else { this.form.linkprot_secret_add.type='."'password'".' }"'.$disabled.' />'.&mt('Visible input').'</label></span> '."\n";                        '<label><input type="checkbox" name="linkprot_visible_add" id="linkprot_visible_add" onclick="if (this.checked) { this.form.linkprot_secret_add.type='."'text'".' } else { this.form.linkprot_secret_add.type='."'password'".' }"'.$disabled.' />'.&mt('Visible input').'</label></span> '."\n";
       }
       if ($ltiauth) {
           $datatable .= '</fieldset>'.
                         '<fieldset id="linkprot_optional_add" style="'.$usersty.'"><legend>'.$lt{'opti'}.'</legend>'.
                         &linkprot_options('add',$itemcount,$disabled,{},\%desc).
                        '</fieldset>';
     }      }
     $datatable .= '</td></tr>';      $datatable .= '</td></tr>';
     $$rowtotal ++;      $$rowtotal ++;
     return $datatable;;      return $datatable;
 }  }
   
 sub linkprot_names {  sub linkprot_names {
     my %lt = &Apache::lonlocal::texthash(      return &Apache::lonlocal::texthash(
                                           'version'   => 'LTI Version',                                            'version'   => 'LTI Version',
                                           'key'       => 'Key',                                            'key'       => 'Key',
                                           'lifetime'  => 'Nonce lifetime (s)',                                            'lifetime'  => 'Nonce lifetime (s)',
                                           'name'      => 'Launcher Application Name',                                            'name'      => 'Launcher Application',
                                           'secret'    => 'Secret',                                            'secret'    => 'Secret',
                                             'requser'   => 'Use identity',
                                             'email'     => 'Email address',
                                             'sourcedid' => 'User ID',
                                             'other'     => 'Other',
                                             'auth'      => 'Display LON-CAPA login page',
                                             'reject'    => 'Discontinue launch process',
                                         );                                          );
     return %lt;  
 }  }
   
 sub check_switchserver {  sub check_switchserver {
     my ($cdom,$cnum) = @_;      my ($cdom,$cnum,$context,$dest) = @_;
     my ($allowed,$switchserver);      my ($allowed,$switchserver,$home);
     my $home = &Apache::lonnet::homeserver($cnum,$cdom);      if ($context eq 'domain') {
     unless ($home eq 'no_host') {          $home = &Apache::lonnet::domain($cdom,'primary');
       } else {
           $home = &Apache::lonnet::homeserver($cnum,$cdom);
       }
       unless (($home eq 'no_host') || ($home eq '')) {
         my @ids=&Apache::lonnet::current_machine_ids();          my @ids=&Apache::lonnet::current_machine_ids();
         foreach my $id (@ids) { if ($id eq $home) { $allowed=1; } }          foreach my $id (@ids) { if ($id eq $home) { $allowed=1; } }
         if (!$allowed) {          if (!$allowed) {
             $switchserver='<a href="/adm/switchserver?otherserver='.$home.'&amp;role='.              $switchserver='<a href="/adm/switchserver?otherserver='.$home.'&amp;role='.
                           &HTML::Entities::encode($env{'request.role'},'\'<>"&').                            &HTML::Entities::encode($env{'request.role'},'\'<>"&').
                           '&amp;destinationurl=/adm/courseprefs">'.&mt('Switch Server').'</a>';                            '&amp;destinationurl='.$dest.'">'.&mt('Switch Server').'</a>';
         }          }
     }      }
     return $switchserver;      return $switchserver;
 }  }
   
   sub linkprot_options {
       my ($num,$itemcount,$disabled,$current,$desc) = @_;
       my %lt;
       if (ref($desc) eq 'HASH') {
           %lt = %{$desc};
       }
       my $userfieldsty = 'none';
       my (%checked,$userfield);
       $checked{'sourcedid'} = ' checked="checked"';
       $checked{'reject'} = ' checked="checked"';
       if (ref($current) eq 'HASH') {
           if (($current->{'mapuser'} ne '') && ($current->{'mapuser'} ne 'lis_person_sourcedid')) {
               $checked{'sourcedid'} = '';
               if ($current->{'mapuser'} eq 'lis_person_contact_email_primary') {
                   $checked{'email'} = ' checked="checked"';
               } else {
                   $checked{'other'} = ' checked="checked"';
                   $userfield = $current->{'mapuser'};
                   $userfieldsty = 'inline-block';
               }
           }
           if (($current->{'notstudent'} ne '') && ($current->{'notstudent'} ne 'reject')) {
               $checked{'reject'} = '';
               $checked{'auth'} = ' checked="checked"';
           }
       }
       my $onclickuser = ' onclick="toggleLinkProtReqUser(this.form,'."'mapuser','userfield','other','inline-block','$num'".');"';
       my $output = '<div class="LC_floatleft"><span class="LC_nobreak">'.
                    &mt('Source of LON-CAPA username in LTI request').':&nbsp;';
       foreach my $option ('sourcedid','email','other') {
           $output .= '<label><input type="radio" name="linkprot_mapuser_'.$num.'" value="'.$option.'"'.
                      $checked{$option}.$onclickuser.$disabled.' />'.$lt{$option}.'</label>'.
                      ($option eq 'other' ? '' : ('&nbsp;'x2) );
       }
       $output .= '</span></div>'.
                  '<div class="LC_floatleft" style="display:'.$userfieldsty.';" id="linkprot_userfield_'.$num.'">'.
                  '<input type="text" name="linkprot_customuser_'.$num.'" '.
                  'value="'.$userfield.'"'.$disabled.' /></div>';
       $output .= '<br />'.
                  '<div class="LC_floatleft"><span class="LC_nobreak">'.
                  &mt('Action when username is not for an enrolled student').':&nbsp;';
       foreach my $option ('reject','auth') {
           $output .= '<label><input type="radio" name="linkprot_notstudent_'.$num.'" value="'.$option.'"'.
                      $checked{$option}.$disabled.' />'.$lt{$option}.'</label>'.
                      ($option eq 'auth' ? '' : ('&nbsp;'x2) );
       }
       $output .= '</span></div>';
       return $output;
   }
   
 sub print_other {  sub print_other {
     my ($cdom,$settings,$allitems,$rowtotal,$crstype,$noedit) = @_;      my ($cdom,$settings,$allitems,$rowtotal,$crstype,$noedit) = @_;
     unless ((ref($settings) eq 'HASH') && (ref($allitems) eq 'ARRAY')) {      unless ((ref($settings) eq 'HASH') && (ref($allitems) eq 'ARRAY')) {
Line 6182  sub change_clone { Line 6558  sub change_clone {
             }              }
         }          }
     }      }
       return;
   }
   
   sub devalidate_remote_courseprefs {
       my ($cdom,$cnum,$cachekeys) = @_;
       return unless (ref($cachekeys) eq 'HASH');
       my %servers = &Apache::lonnet::internet_dom_servers($cdom);
       my %thismachine;
       map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids();
       my @posscached = ('courselti');
       if (keys(%servers)) {
           foreach my $server (keys(%servers)) {
               next if ($thismachine{$server});
               my @cached;
               foreach my $name (@posscached) {
                   if ($cachekeys->{$name}) {
                       push(@cached,&escape($name).':'.&escape($cdom.'_'.$cnum));
                   }
               }
               if (@cached) {
                   &Apache::lonnet::remote_devalidate_cache($server,\@cached);
               }
           }
       }
     return;      return;
 }  }
   

Removed from v.1.99  
changed lines
  Added in v.1.108


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