Diff for /loncom/interface/courseprefs.pm between versions 1.49.2.25 and 1.49.2.28.2.6

version 1.49.2.25, 2020/02/12 17:27:40 version 1.49.2.28.2.6, 2022/02/21 16:11:18
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 %linkprot=&Apache::lonnet::dump('lti',$cdom,$cnum,undef,undef,undef,1);
       my %ltienc = &Apache::lonnet::dump('nohist_ltienc',$cdom,$cnum,undef,undef,undef,1);
       foreach my $id (keys(%linkprot)) {
           if (ref($linkprot{$id}) eq 'HASH') {
               if (ref($ltienc{$id}) eq 'HASH') {
                   $values{'linkprot'}{$id} = { %{$linkprot{$id}}, %{$ltienc{$id}} };
               } else {
                   $values{'linkprot'}{$id} = $linkprot{$id};
               }
           }
           unless ($phase eq 'process') {
               if (ref($values{'linkprot'}{$id}) eq 'HASH') {
                   delete($values{'linkprot'}{$id}{'secret'});
               }
           }
       }
       if ($linkprot{'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',
                        'spreadsheet','bridgetasks','other');                         'menuitems','linkprot','spreadsheet','bridgetasks',
                          'other');
   
     my %prefs = (      my %prefs = (
         'courseinfo' =>          'courseinfo' =>
Line 464  sub handler { Line 489  sub handler {
                      help => 'Course_Prefs_Display',                       help => 'Course_Prefs_Display',
                      ordered => ['default_xml_style','pageseparators',                       ordered => ['default_xml_style','pageseparators',
                                  'disable_receipt_display','texengine',                                   'disable_receipt_display','texengine',
                                  'tthoptions','uselcmath','usejsme'],                                   'tthoptions','uselcmath','usejsme','inline_chem'],
                       itemtext => {                        itemtext => {
                           default_xml_style       => 'Default XML style file',                            default_xml_style       => 'Default XML style file',
                           pageseparators          => 'Visibly Separate Items on Pages',                            pageseparators          => 'Visibly Separate Items on Pages',
Line 473  sub handler { Line 498  sub handler {
                           tthoptions              => 'Default set of options to pass to tth/m when converting TeX',                            tthoptions              => 'Default set of options to pass to tth/m when converting TeX',
                           uselcmath               => 'Student formula entry uses inline preview, not DragMath pop-up',                            uselcmath               => 'Student formula entry uses inline preview, not DragMath pop-up',
                           usejsme                 => 'Molecule editor uses JSME (HTML5) in place of JME (Java)',                            usejsme                 => 'Molecule editor uses JSME (HTML5) in place of JME (Java)',
                             inline_chem             => 'Chemical reaction response uses inline preview, not pop-up',
                                   },                                    },
                   },                    },
         'grading' =>          'grading' =>
Line 527  sub handler { Line 553  sub handler {
                         suppress_embed_prompt => 'Hide upload references prompt if uploading file to portfolio',                          suppress_embed_prompt => 'Hide upload references prompt if uploading file to portfolio',
                                 },                                  },
                   },                    },
           'menuitems' =>
                      {
                        text => 'Menu display',
                        help => 'Course_Prefs_Menus',
                        header => [{col1 => 'Default Menu',
                                    col2 => 'Value',},
                                   {col1 => 'Menu collections',
                                    col2 => 'Settings',
                                   }],
                        ordered => ['menudefault','menucollections'],
                        itemtext => {
                            menudefault     => 'Choose default collection of menu items for course',
                            menucollections => 'Menu collections',
                                    },
                      },
           'linkprot' =>
                      {
                        text => 'Link protection',
                        help => 'Course_Prefs_Linkprotection',
                        header => [{col1 => 'Item',
                                    col2 => 'Settings',
                                   }],
                      },
         'other' =>          'other' =>
                   { text => 'Other settings',                    { text => 'Other settings',
                     help => 'Course_Prefs_Other',                      help => 'Course_Prefs_Other',
Line 542  sub handler { Line 591  sub handler {
                                                   $cnum,undef,\@allitems,                                                    $cnum,undef,\@allitems,
                                                   'coursepref',$parm_permission);                                                    'coursepref',$parm_permission);
     } elsif (($phase eq 'display') && ($parm_permission->{'display'})) {      } elsif (($phase eq 'display') && ($parm_permission->{'display'})) {
         my $jscript = &get_jscript($cid,$cdom,$phase,$crstype,\%values);          my $noedit;
           if (ref($parm_permission) eq 'HASH') {
               unless ($parm_permission->{'process'}) {
                   $noedit = 1;
               }
           }
           my $jscript = &get_jscript($cid,$cdom,$phase,$crstype,\%values,$noedit);
         my @allitems = &get_allitems(%prefs);          my @allitems = &get_allitems(%prefs);
         &Apache::lonconfigsettings::display_settings($r,$cdom,$phase,$context,          &Apache::lonconfigsettings::display_settings($r,$cdom,$phase,$context,
             \@prefs_order,\%prefs,\%values,undef,$jscript,\@allitems,$crstype,              \@prefs_order,\%prefs,\%values,$cnum,$jscript,\@allitems,$crstype,
             'coursepref',$parm_permission);              'coursepref',$parm_permission);
     } else {      } else {
         &Apache::lonconfigsettings::display_choices($r,$phase,$context,          &Apache::lonconfigsettings::display_choices($r,$phase,$context,
Line 598  sub get_allitems { Line 653  sub get_allitems {
 }  }
   
 sub print_config_box {  sub print_config_box {
     my ($r,$cdom,$phase,$action,$item,$settings,$allitems,$crstype,$parm_permission) = @_;      my ($r,$cdom,$cnum,$phase,$action,$item,$settings,$allitems,$crstype,$parm_permission) = @_;
     my $ordered = $item->{'ordered'};      my $ordered = $item->{'ordered'};
     my $itemtext = $item->{'itemtext'};      my $itemtext = $item->{'itemtext'};
     my $noedit;      my $noedit;
Line 619  sub print_config_box { Line 674  sub print_config_box {
     }      }
     $output .= '</span></th>'."\n".      $output .= '</span></th>'."\n".
                '</tr>';                 '</tr>';
     if (($action eq 'feedback') || ($action eq 'classlists')) {      if (($action eq 'feedback') || ($action eq 'classlists') || ($action eq 'menuitems')) {
         $output .= '          $output .= '
           <tr>            <tr>
            <td>             <td>
Line 644  sub print_config_box { Line 699  sub print_config_box {
             $output .= &print_feedback('top',$cdom,$settings,$ordered,$itemtext,\$rowtotal,$noedit);              $output .= &print_feedback('top',$cdom,$settings,$ordered,$itemtext,\$rowtotal,$noedit);
         } elsif ($action eq 'classlists') {          } elsif ($action eq 'classlists') {
             $output .= &print_classlists('top',$cdom,$settings,$itemtext,\$rowtotal,$crstype,$noedit);              $output .= &print_classlists('top',$cdom,$settings,$itemtext,\$rowtotal,$crstype,$noedit);
           } elsif ($action eq 'menuitems') {
               $output .= &print_menuitems('top',$cdom,$settings,$itemtext,\$rowtotal,$crstype,$noedit);
         }          }
         $output .= '          $output .= '
            </table>             </table>
Line 722  sub print_config_box { Line 779  sub print_config_box {
         $output .= &print_spreadsheet($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype,$noedit);          $output .= &print_spreadsheet($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype,$noedit);
     } elsif ($action eq 'bridgetasks') {      } elsif ($action eq 'bridgetasks') {
         $output .= &print_bridgetasks($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype,$noedit);          $output .= &print_bridgetasks($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype,$noedit);
       } elsif ($action eq 'menuitems') {
           $output .= &print_menuitems('bottom',$cdom,$settings,$itemtext,\$rowtotal,$crstype,$noedit);
       } elsif ($action eq 'linkprot') {
           $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 734  sub print_config_box { Line 795  sub print_config_box {
 }  }
   
 sub process_changes {  sub process_changes {
     my ($cdom,$action,$values,$item,$changes,$allitems,$disallowed,$crstype) = @_;      my ($cdom,$cnum,$action,$values,$item,$changes,$allitems,$disallowed,$crstype) = @_;
     my %newvalues;      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 752  sub process_changes { Line 813  sub process_changes {
                         }                          }
                     }                      }
                 }                  }
               } elsif ($action eq 'linkprot') {
                   if (ref($values->{$action}) eq 'HASH') {
                       foreach my $id (keys(%{$values->{$action}})) {
                           if ($id =~ /^\d+$/) {
                               push(@ordered,$id);
                           }
                       }
                   }
                   @ordered = sort { $a <=> $b } @ordered;
                   if (($env{'form.linkprot_add'}) && ($env{'form.linkprot_maxnum'} =~ /^\d+$/)) {
                       push(@ordered,$env{'form.linkprot_maxnum'});
                   }
             } elsif (ref($item->{'ordered'}) eq 'ARRAY') {              } elsif (ref($item->{'ordered'}) eq 'ARRAY') {
                 if ($action eq 'courseinfo') {                  if ($action eq 'courseinfo') {
                     my ($can_toggle_cat,$can_categorize) =                      my ($can_toggle_cat,$can_categorize) =
Line 814  sub process_changes { Line 887  sub process_changes {
                             $changes->{$ext_entry} = $newvalues{$ext_entry};                              $changes->{$ext_entry} = $newvalues{$ext_entry};
                         }                          }
                     }                      }
                   } elsif ($action eq 'menuitems') {
                       my (%current,@colls);
                       my $next = 1;
                       if ($values->{'menucollections'}) {
                           foreach my $item (split(/;/,$values->{'menucollections'})) {
                               my ($num,$value) = split(/\%/,$item);
                               if ($num =~ /^\d+$/) {
                                   unless (grep(/^$num$/,@colls)) {
                                       push(@colls,$num);
                                   }
                                   my @entries = split(/\&/,$value);
                                   foreach my $entry (@entries) {
                                       my ($name,$fields) = split(/=/,$entry);
                                       $current{$num}{$name} = $fields;
                                   }
                               }
                           }
                       }
                       if (@colls) {
                           @colls = sort { $a <=> $b } @colls;
                           $next += $colls[-1];
                       }
                       if ($env{'form.menucollections_add'} eq $next) {
                           push(@colls,$next);
                       }
                       my $currdef = $values->{'menudefault'};
                       my $possdef = $env{'form.menudefault'};
                       if (($possdef =~ /^\d+$/) && (grep(/^$possdef$/,@colls))) {
                           if ($currdef ne $possdef) {
                               $changes->{'menudefault'} = $possdef;
                           }
                       } elsif ($currdef) {
                           $changes->{'menudefault'} = '';
                       }
                       my $menucoll;
                       if (@colls) {
                           my ($ordered,$cats) = &menuitems_categories();
                           my %shortcats = &menuitems_abbreviations();
                           foreach my $num (@colls) {
                               my ($entry,%include);
                               map { $include{$_}= 1; } &Apache::loncommon::get_env_multiple('form.menucollections_'.$num);
                               foreach my $item (@{$ordered}) {
                                   if ($item eq 'shown') {
                                       foreach my $type (@{$cats->{$item}}) {
                                           $entry .= $type.'=';
                                           if ($include{$type}) {
                                               $entry .= 'y';
                                           } else {
                                               $entry .= 'n';
                                           }
                                           $entry .= '&';
                                       }
                                   } else {
                                       $entry .= $shortcats{$item}.'=';
                                       foreach my $type (@{$cats->{$item}}) {
                                           if ($include{$type}) {
                                               $entry .= $type.',';
                                           }
                                       }
                                       $entry =~ s/,$//;
                                       $entry .= '&';
                                   }
                               }
                               $entry =~ s/\&$//;
                               if ($menucoll) {
                                   $menucoll .= ';';
                               }
                               $menucoll .= $num.'%'.$entry;
                           }
                           if ($menucoll ne $values->{'menucollections'}) {
                               $changes->{'menucollections'} = $menucoll;
                           }
                       } elsif ($values->{'menucollections'}) {
                           $changes->{'menucollections'} = '';
                       }
                   } elsif ($action eq 'linkprot') {
                       if (ref($values) eq 'HASH') {
                           $errors = &process_linkprot($cdom,$cnum,$values->{$action},$changes,'course');
                       }
                 } else {                  } else {
                     foreach my $entry (@ordered) {                      foreach my $entry (@ordered) {
                         if ($entry eq 'cloners') {                          if ($entry eq 'cloners') {
Line 854  sub process_changes { Line 1006  sub process_changes {
                                     my $clonedom = $env{'form.cloners_newdom'};                                      my $clonedom = $env{'form.cloners_newdom'};
                                     if (&check_clone($clonedom,$disallowed) eq 'ok') {                                      if (&check_clone($clonedom,$disallowed) eq 'ok') {
                                         my $newdom = '*:'.$env{'form.cloners_newdom'};                                          my $newdom = '*:'.$env{'form.cloners_newdom'};
                                         if (@clonedoms) {                                           if (@clonedoms) {
                                             if (!grep(/^\Q$newdom\E$/,@clonedoms)) {                                              if (!grep(/^\Q$newdom\E$/,@clonedoms)) {
                                                 $newvalues{$entry} .= ','.$newdom;                                                  $newvalues{$entry} .= ','.$newdom;
                                             }                                              }
Line 943  sub process_changes { Line 1095  sub process_changes {
                                         $autocoowner = $domconf{'autoenroll'}{'co-owners'};                                          $autocoowner = $domconf{'autoenroll'}{'co-owners'};
                                     }                                      }
                                 }                                  }
                                 unless ($autocoowner) {                                  if ($autocoowner) {
                                       $newvalues{'co-owners'} = $values->{'internal.co-owners'}; 
                                   } else {
                                     my @keepcoowners = &Apache::loncommon::get_env_multiple('form.coowners');                                      my @keepcoowners = &Apache::loncommon::get_env_multiple('form.coowners');
                                     my @pendingcoowners = &Apache::loncommon::get_env_multiple('form.pendingcoowners');                                      my @pendingcoowners = &Apache::loncommon::get_env_multiple('form.pendingcoowners');
                                     my @invitecoowners =  &Apache::loncommon::get_env_multiple('form.invitecoowners');                                      my @invitecoowners =  &Apache::loncommon::get_env_multiple('form.invitecoowners');
Line 967  sub process_changes { Line 1121  sub process_changes {
                                 my $udom = $env{'user.domain'};                                  my $udom = $env{'user.domain'};
                                 my $pendingcoowners = $values->{'internal.pendingco-owners'};                                  my $pendingcoowners = $values->{'internal.pendingco-owners'};
                                 my @pendingcoown = split(',',$pendingcoowners);                                  my @pendingcoown = split(',',$pendingcoowners);
                                 if ($env{'form.pending_coowoner'}) {                                  if ($env{'form.pending_coowner'}) {
                                     foreach my $item (@pendingcoown) {                                      foreach my $item (@pendingcoown) {
                                         unless ($item eq $uname.':'.$udom) {                                          unless ($item eq $uname.':'.$udom) {
                                             push(@newpending,$item);                                              push(@newpending,$item);
                                         }                                          }
                                     }                                      }
                                     @newcoown = @currcoown;                                      @newcoown = @currcoown;
                                     if ($env{'form.pending_coowoner'} eq 'accept') {                                      if ($env{'form.pending_coowner'} eq 'accept') {
                                         unless (grep(/^\Q$uname\E:\Q$udom\E$/,@currcoown)) {                                          unless (grep(/^\Q$uname\E:\Q$udom\E$/,@currcoown)) {
                                             push(@newcoown,$uname.':'.$udom);                                              push(@newcoown,$uname.':'.$udom);
                                         }                                          }
                                     }                                      }
                                 } elsif ($env{'form.remove_coowoner'}) {                                  } elsif ($env{'form.remove_coowner'}) {
                                     foreach my $item (@currcoown) {                                      foreach my $item (@currcoown) {
                                         unless ($item eq $uname.':'.$udom) {                                          unless ($item eq $uname.':'.$udom) {
                                             push(@newcoown,$item);                                              push(@newcoown,$item);
Line 988  sub process_changes { Line 1142  sub process_changes {
                                     if ($pendingcoowners ne '') {                                      if ($pendingcoowners ne '') {
                                         @newpending = @pendingcoown;                                          @newpending = @pendingcoown;
                                     }                                      }
                                   } else {
                                       @newcoown = @currcoown;
                                 }                                  }
                                 $newvalues{'pendingco-owners'} = join(',',sort(@newpending));                                  $newvalues{'pendingco-owners'} = join(',',sort(@newpending));
                                 $newvalues{'co-owners'} = join(',',sort(@newcoown));                                  $newvalues{'co-owners'} = join(',',sort(@newcoown));
Line 1266  sub process_changes { Line 1422  sub process_changes {
             }              }
         }          }
     }      }
     return;      return $errors;
   }
   
   sub process_linkprot {
       my ($cdom,$cnum,$values,$changes,$context) = @_;
       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'};
                   }
               } 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};
           }
       }
       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 = {
                         lock => $env{'user.name'}.
                                 ':'.$env{'user.domain'},
                      };
       my $tries = 0;
       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);
       while (($gotlock ne 'ok') && ($tries<10)) {
           $tries ++;
           sleep (0.1);
           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') {
           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'}) {
               delete($currids{'lock'});
               if (keys(%currids)) {
                   my @curr = sort { $a <=> $b } keys(%currids);
                   if ($curr[-1] =~ /^\d+$/) {
                       $id = 1 + $curr[-1];
                   } else {
                       $id = 1;
                   }
               } else {
                   $id = 1;
               }
               if ($id) {
                   if ($context eq 'domain') {
                        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 {
                   $error = 'nonumber';
               }
           }
           my $dellockoutcome;
           if ($context eq 'domain') {
               $dellockoutcome = &Apache::lonnet::del_dom('linkprot',['lock'],$cdom);
           } else {
               $dellockoutcome = &Apache::lonnet::del('lti',['lock'],$cdom,$cnum);
           }
       } else {
           $error = 'nolock';
       }
       return ($id,$error);
 }  }
   
 sub get_sec_str {  sub get_sec_str {
Line 1311  sub check_clone { Line 1736  sub check_clone {
 sub store_changes {  sub store_changes {
     my ($cdom,$cnum,$prefs_order,$actions,$prefs,$values,$changes,$crstype) = @_;      my ($cdom,$cnum,$prefs_order,$actions,$prefs,$values,$changes,$crstype) = @_;
     my ($chome,$output);      my ($chome,$output);
     my (%storehash,@delkeys,@need_env_update,@oldcloner);      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->{'linkprot'}) eq 'HASH') {
               %oldlinkprot = %{$values->{'linkprot'}};
           }
           delete($values->{'linkprot'});
         %storehash = %{$values};          %storehash = %{$values};
     } else {      } else {
         if ($crstype eq 'Community') {          if ($crstype eq 'Community') {
Line 1322  sub store_changes { Line 1751  sub store_changes {
         }          }
         return $output;          return $output;
     }      }
       my ($numchanges,$skipstore);
       if (ref($changes) eq 'HASH') {
           $numchanges = scalar(keys(%{$changes}));
           if (($numchanges == 1) && (exists($changes->{'linkprot'}))) {
               $skipstore = 1;
           } elsif (!$numchanges) {
               if ($crstype eq 'Community') {
                   $output = &mt('No changes made to community settings.');
               } else {
                   $output = &mt('No changes made to course settings.');
               }
               return $output;
           }
       }
     my %yesno = (      my %yesno = (
                  hidefromcat           => '1',                   hidefromcat           => '1',
                  problem_stream_switch => '1',                   problem_stream_switch => '1',
Line 1347  sub store_changes { Line 1790  sub store_changes {
                                            "'$storehash{$key}'")).'</li>';                                             "'$storehash{$key}'")).'</li>';
                             }                              }
                         }                          }
                       } elsif ($item eq 'linkprot') {
                           $output .= &store_linkprot($cdom,$cnum,'course',$changes->{$item},\%oldlinkprot);
                     } 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 1463  sub store_changes { Line 1908  sub store_changes {
                                             }                                              }
                                         }                                          }
                                         $displayname = &mt($text);                                          $displayname = &mt($text);
                                       } elsif ($item eq 'menuitems') {
                                           unless ($changes->{$item}{$key} eq '') {
                                               if ($key eq 'menudefault') {
                                                   $displayname = &mt('Default collection of menu items');
                                                   $displayval = &mt('Collection: [_1]',
                                                                     $changes->{$item}{$key});
                                               } elsif ($key eq 'menucollections') {
                                                   $displayval = &menucollections_display($changes->{$item}{$key});
                                               }
                                           }
                                     } else {                                      } else {
                                         $displayname = &mt($text);                                          $displayname = &mt($text);
                                     }                                      }
Line 1475  sub store_changes { Line 1930  sub store_changes {
                                         $displayval = &Apache::lonlocal::locallocaltime($displayval);                                          $displayval = &Apache::lonlocal::locallocaltime($displayval);
                                     } elsif ($key eq 'categories') {                                      } elsif ($key eq 'categories') {
                                         $displayval = $env{'form.categories_display'};                                          $displayval = $env{'form.categories_display'};
                                     } elsif (($key eq 'canuse_pdfforms') || ($key eq 'usejsme') || ($key eq 'uselcmath')) {                                      } elsif (($key eq 'canuse_pdfforms') || ($key eq 'usejsme') ||
                                                ($key eq 'uselcmath') || ($key eq 'inline_chem')) {
                                         if ($changes->{$item}{$key} eq '1') {                                          if ($changes->{$item}{$key} eq '1') {
                                             $displayval = &mt('Yes');                                              $displayval = &mt('Yes');
                                         } elsif ($changes->{$item}{$key} eq '0') {                                          } elsif ($changes->{$item}{$key} eq '0') {
Line 1507  sub store_changes { Line 1963  sub store_changes {
                                                 }                                                  }
                                             }                                              }
                                             unless (&Apache::lonnet::is_course_owner($cdom,$cnum)) {                                              unless (&Apache::lonnet::is_course_owner($cdom,$cnum)) {
                                                 if ($env{'form.pending_coowoner'} eq 'accept') {                                                  if ($env{'form.pending_coowner'} eq 'accept') {
                                                         $displayval = &mt('on');                                                          $displayval = &mt('on');
                                                 } elsif ($env{'form.pending_coowoner'} eq 'decline') {                                                  } elsif ($env{'form.pending_coowner'} eq 'decline') {
                                                         $displayval = '';                                                          $displayval = '';
                                                         $output .= '<li>'.&Apache::lonhtmlcommon::confirm_success(&mt('Invitation to be co-owner declined')).'</li>';                                                          $output .= '<li>'.&Apache::lonhtmlcommon::confirm_success(&mt('Invitation to be co-owner declined')).'</li>';
                                                 } elsif ($env{'form.remove_coowoner'}) {                                                  } elsif ($env{'form.remove_coowner'}) {
                                                     $displayval = &mt('off');                                                      $displayval = &mt('off');
                                                 }                                                  }
                                                 if ($displayval) {                                                  if ($displayval) {
Line 1525  sub store_changes { Line 1981  sub store_changes {
                                         }                                          }
                                     } elsif ($changes->{$item}{$key} eq '') {                                      } elsif ($changes->{$item}{$key} eq '') {
                                         push(@delkeys,$key);                                          push(@delkeys,$key);
                                         $output .= '<li>'.&Apache::lonhtmlcommon::confirm_success(&mt('Deleted setting for [_1]',                                          if ($item eq 'menuitems') {
                                                    '<i>'.$displayname.'</i>')).'</li>';                                              if ($key eq 'menudefault') {
                                                   $output .= '<li>'.&mt("Default collection of menu items set to: 'Standard' (all menus shown)").'</li>';
                                               } elsif ($key eq 'menucollections') {
                                                   $output .= '<li>'.&mt('Specific collections of menus no longer available').'</li>';
                                               }
                                           } else {
                                               $output .= '<li>'.&Apache::lonhtmlcommon::confirm_success(&mt('Deleted setting for [_1]',
                                                          '<i>'.$displayname.'</i>')).'</li>';
                                           }
                                       } elsif ($key eq 'menucollections') {
                                           $output .= '<li>'.&Apache::lonhtmlcommon::confirm_success(&mt('Numbered menu collections:')).'<br />'.
                                                      $displayval.'</li>';
                                     } else {                                      } else {
                                         $output .= '<li>'.&Apache::lonhtmlcommon::confirm_success(&mt('[_1] set to [_2]',                                          $output .= '<li>'.&Apache::lonhtmlcommon::confirm_success(&mt('[_1] set to [_2]',
                                                    '<i>'.$displayname.'</i>',                                                     '<i>'.$displayname.'</i>',
Line 1582  sub store_changes { Line 2049  sub store_changes {
             }              }
         }          }
     }      }
       if ($skipstore) {
           return $output;
       }
     if (&Apache::lonnet::put('environment',\%storehash,$cdom,$cnum) eq 'ok') {      if (&Apache::lonnet::put('environment',\%storehash,$cdom,$cnum) eq 'ok') {
         if (ref($changes) eq 'HASH') {          if (ref($changes) eq 'HASH') {
             if (ref($changes->{'courseinfo'}) eq 'HASH') {              if (ref($changes->{'courseinfo'}) eq 'HASH') {
Line 1624  sub store_changes { Line 2094  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 1752  sub get_course { Line 2373  sub get_course {
 }  }
   
 sub get_jscript {  sub get_jscript {
     my ($cid,$cdom,$phase,$crstype,$settings) = @_;      my ($cid,$cdom,$phase,$crstype,$settings,$noedit) = @_;
     my ($can_toggle_cat,$can_categorize) = &can_modify_catsettings($cdom,$crstype);      my ($can_toggle_cat,$can_categorize) = &can_modify_catsettings($cdom,$crstype);
     my ($jscript,$categorize_js,$loncaparev_js,$instcode_js);      my ($jscript,$categorize_js,$loncaparev_js,$instcode_js);
     my $stubrowse_js = &Apache::loncommon::studentbrowser_javascript();      my $stubrowse_js = &Apache::loncommon::studentbrowser_javascript();
Line 1878  function syllabusinfo() { Line 2499  function syllabusinfo() {
     }      }
 }  }
 ENDSCRIPT  ENDSCRIPT
       my $menuitems_js;
       unless ($noedit) {
           my $collections;
           my $next = 1;
           if (ref($settings) eq 'HASH') {
               if ($settings->{'menucollections'} ne '') {
                   my @current;
                   foreach my $item (split(/;/,$settings->{'menucollections'})) {
                       my ($num) = split(/\%/,$item);
                       if ($num =~ /^\d+$/) {
                           push(@current,$num);
                       }
                   }
                   $collections = join("','",sort { $a <=> $b } @current);
                   if ($collections) {
                       $collections = "'$collections'";
                   }
                   $next += $current[-1];
               }
           }
           my $deftext = &mt('Standard (all menus shown)');
           $menuitems_js = <<ENDSCRIPT;
   function toggleAddmenucoll() {
       if (document.getElementById('menucollections_add')) {
           var state = 'none';
           var add = document.getElementById('menucollections_add').checked;
           if (add) {
               state = 'inline-block';
           }
           var fieldsets = new Array('shown','text','links','list','inline');
           for (var i=0; i<fieldsets.length; i++) {
               if (document.getElementById('addmenucoll_'+fieldsets[i])) {
                   document.getElementById('addmenucoll_'+fieldsets[i]).style.display = state;
               }
           }
           var box = document.getElementsByClassName('LC_menucoll_add');
           if (box.length) {
               for (var i=0; i<box.length; i++) {
                   if (add) {
                       box[i].checked = true;
                   } else {
                       box[i].checked = false;
                   }
               }
           }
           if (document.getElementById('menudefault')) {
               var menudef = document.getElementById('menudefault');
               var currsel = menudef.selectedIndex;
               var colls = new Array($collections);
               menudef.options.length = 0;
               if (!add) {
                   if (currsel == 1 + colls.length) {
                       currsel = 0;
                   }
               }
               if (currsel == 0) {
                   menudef.options[0] = new Option('$deftext','',true,true);
               } else {
                   menudef.options[0] = new Option('$deftext','',false,false);
               }
               if (colls.length) {
                   for (var i=0; i<colls.length; i++) {
                       var idx = i+1;
                       if (currsel == colls[i]) {
                           menudef.options[idx] = new Option(colls[i],colls[i],true,true);
                       } else {
                           menudef.options[idx] = new Option(colls[i],colls[i],false,false);
                       }
                   }
               }
               if (add) {
                   var addidx = 1 + colls.length;
                   if (currsel == addidx) {
                        menudef.options[addidx] = new Option('$next','$next',true,true);
                   } else {
                       menudef.options[addidx] = new Option('$next','$next',false,false);
                   }
               }
           }
       }
   }
   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".'//]]>'."\n".                 $syllabus_js."\n".$menuitems_js."\n".
                  &linkprot_javascript()."\n".'//]]>'."\n".
                '</script>'."\n".$stubrowse_js."\n";                 '</script>'."\n".$stubrowse_js."\n";
     return $jscript;      return $jscript;
 }  }
Line 1968  function getIndexByName(item) { Line 2673  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;
   }
   ENDSCRIPT
   
   }
   
   
 sub print_courseinfo {  sub print_courseinfo {
     my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype,$noedit) = @_;      my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype,$noedit) = @_;
Line 3171  sub coowner_invitations { Line 3938  sub coowner_invitations {
         @pendingcoown = split(',',$pendingcoowners);          @pendingcoown = split(',',$pendingcoowners);
     }      }
     if (ref($currcoownref) eq 'ARRAY') {      if (ref($currcoownref) eq 'ARRAY') {
         @currcoown == @{$currcoownref};          @currcoown = @{$currcoownref};
     }      }
     my $disabled;      my $disabled;
     if ($noedit) {      if ($noedit) {
Line 3235  sub manage_coownership  { Line 4002  sub manage_coownership  {
         @pendingcoown = split(',',$pendingcoowners);          @pendingcoown = split(',',$pendingcoowners);
     }      }
     if (ref($currcoownref) eq 'ARRAY') {      if (ref($currcoownref) eq 'ARRAY') {
         @currcoown == @{$currcoownref};          @currcoown = @{$currcoownref};
     }      }
     my $disabled;      my $disabled;
     if ($noedit) {      if ($noedit) {
Line 3270  sub manage_coownership  { Line 4037  sub manage_coownership  {
         }          }
         $output .= '<span class="LC_nobreak">';          $output .= '<span class="LC_nobreak">';
         if ($is_coowner) {          if ($is_coowner) {
             $output .= &mt('You are currently a co-owner:').'&nbsp;<label><input type="checkbox" name="remove_coowoner" value="'.$uname.':'.$udom.'" />'.&mt('Discontinue?').'</label>';              $output .= &mt('You are currently a co-owner:').'&nbsp;<label><input type="checkbox" name="remove_coowner" value="'.$uname.':'.$udom.'" />'.&mt('Discontinue?').'</label>';
         } else {          } else {
             $output .= &mt('The course owner has invited you to become a co-owner:').'&nbsp;<label><input type="radio" name="pending_coowoner" value="accept"'.$disabled.' />'.&mt('Accept?').'</label>'.('&nbsp;'x2).              $output .= &mt('The course owner has invited you to become a co-owner:').'&nbsp;<label><input type="radio" name="pending_coowner" value="accept"'.$disabled.' />'.&mt('Accept?').'</label>'.('&nbsp;'x2).
                        '<label><input type="radio" name=pending_coowoner" value="decline"'.$disabled.' />'.&mt('Decline?').'</label>';                         '<label><input type="radio" name=pending_coowner" value="decline"'.$disabled.' />'.&mt('Decline?').'</label>';
         }          }
         $output .= '</span>';          $output .= '</span>';
         if (@currcoown) {          if (@currcoown) {
Line 4016  sub print_appearance { Line 4783  sub print_appearance {
                    text => '<b>'.&mt($itemtext->{'usejsme'}).'</b>',                     text => '<b>'.&mt($itemtext->{'usejsme'}).'</b>',
                    input => 'radio',                     input => 'radio',
                  },                   },
            'inline_chem' => {
                      text => '<b>'.&mt($itemtext->{'inline_chem'}).'</b>',
                      input => 'radio',
                    },
     );      );
     return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype,'appearance',$noedit);      return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype,'appearance',$noedit);
 }  }
Line 4206  sub print_bridgetasks { Line 4977  sub print_bridgetasks {
     return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype,'bridgetasks',$noedit);      return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype,'bridgetasks',$noedit);
 }  }
   
   sub ltimenu_titles {
       return &Apache::lonlocal::texthash(
                                           fullname    => 'Full name',
                                           coursetitle => 'Course title',
                                           role        => 'Role',
                                           logout      => 'Logout',
                                           grades      => 'Grades',
       );
   }
   
   sub print_menuitems {
       my ($position,$cdom,$settings,$itemtext,$rowtotal,$crstype,$noedit) = @_;
       unless ((ref($settings) eq 'HASH') && (ref($itemtext) eq 'HASH')) {
           return;
       }
       if ($position eq 'top') {
           my (%defaultmenu_options,@defaultmenu_order,$addcollection);
           if ($settings->{'menucollections'} ne '') {
               foreach my $item (split(/;/,$settings->{'menucollections'})) {
                   my ($num,$value) = split(/\%/,$item);
                   if ($num =~ /^\d+$/) {
                       $defaultmenu_options{$num} = $num;
                   }
               }
               @defaultmenu_order = sort { $a <=> $b } keys(%defaultmenu_options);
               $addcollection = $defaultmenu_order[-1] + 1;
           } else {
               $addcollection = 1;
           }
           $defaultmenu_options{$addcollection} = $addcollection;
           my %items = (
               'menudefault' => {
                      text => '<b>'.&mt($itemtext->{'menudefault'}).'</b><br />'.
                              &mt("(can be overriden in deep-link context)"),
                      input => 'selectbox',
                      options => \%defaultmenu_options,
                      order  => \@defaultmenu_order,
                      nullval => &mt('Standard (all menus shown)'),
                               },
           );
           return &make_item_rows($cdom,\%items,['menudefault'],$settings,$rowtotal,$crstype,'menuitems',$noedit);
       } else {
           my %menu;
           my $count = 0;
           my $next = 1;
           my ($datatable,$disabled);
           if ($noedit) {
               $disabled = ' disabled="disabled"';
           }
   
           my ($ordered,$cats) = &menuitems_categories();
           my @order = @{$ordered};
           my %categories = %{$cats};
           my %menutitles = &menuitems_titles();
           my %menufields = &menuitems_fields();
   
           if ($settings->{'menucollections'} ne '') {
               foreach my $item (split(/;/,$settings->{'menucollections'})) {
                   my ($num,$value) = split(/\%/,$item);
                   if ($num =~ /^\d+$/) {
                       my @entries = split(/\&/,$value);
                       foreach my $entry (@entries) {
                           my ($name,$fields) = split(/=/,$entry);
                           $menu{$num}{$name} = $fields;
                       }
                   }
               }
               if (keys(%menu)) {
                   my @current = sort { $a <=> $b } keys(%menu);
                   $next += $current[-1];
                   foreach my $num (@current) {
                       my %checked;
                       my $on = ' checked="checked"';
                       foreach my $key (keys(%{$menu{$num}})) {
                           if (($key eq 'top') || ($key eq 'inline') || ($key eq 'foot') || ($key eq 'main')) {
                               if ($menu{$num}{$key} eq 'y') {
                                   $checked{$key} = $on;
                               }
                           } else {
                               foreach my $field (split(/,/,$menu{$num}{$key})) {
                                   if (exists($menufields{$field})) {
                                       $checked{$field} = $on;
                                   }
                               }
                           }
                       }
                       if (ref($menu{$num}) eq 'HASH') {
                           $datatable .= &item_table_row_start('<em class="LC_nav_bar">'.$num.'</em>',$count,'','','','LC_left_item');
                           foreach my $category (@order) {
                               if ((ref($categories{$category}) eq 'ARRAY') && (@{$categories{$category}} > 0)) {
                                   $datatable .= '<fieldset style="vertical-align:top; display:inline-block"><legend>'.$menutitles{$category}.'</legend>'."\n";
                                   if ($category eq 'text') {
                                       $datatable .= '<i>'.&mt('Header').'</i><br />';
                                   }
                                   foreach my $field (@{$categories{$category}}) {
                                       if ($field eq 'disc') {
                                           $datatable .= '<br /><i>'.&mt('Footer').'</i><br />';
                                       }
                                       $datatable .= '<label><input type="checkbox" name="menucollections_'.$num.'" value="'.$field.'"'.$checked{$field}.$disabled.' />'.
                                                     $menufields{$field}.'</label><br />';
                                   }
                                   $datatable .= '</fieldset>';
                               }
                           }
                           $datatable .= &item_table_row_end();
                           $count ++;
                       }
                   }
               }
           } elsif ($noedit) {
               my $text = &mt('No menu collections defined for this course.');
               $datatable .= &item_table_row_start($text,$count);
           }
           unless ($noedit) {
               my $add = '<label><input type="checkbox" name="menucollections_add" id="menucollections_add" value="'.$next.'" '.
                         'onclick="javascript:toggleAddmenucoll();" />'.&mt('Add').'</label>';
               $datatable .= &item_table_row_start($add,$count,'','','','LC_left_item');
               foreach my $category (@order) {
                   if ((ref($categories{$category}) eq 'ARRAY') && (@{$categories{$category}} > 0)) {
                       $datatable .= '<fieldset id="addmenucoll_'.$category.'" style="display:none; vertical-align:top;"><legend>'.$menutitles{$category}.'</legend>'."\n";
                       foreach my $field (@{$categories{$category}}) {
                           $datatable .= '<label><input type="checkbox" class="LC_menucoll_add" name="menucollections_'.$next.'" value="'.$field.'"'.$disabled.' />'.
                                         $menufields{$field}.'</label><br />';
                       }
                       $datatable .= '</fieldset>';
                   }
               }
               $datatable .= &item_table_row_end();
               $count ++;
           }
           return $datatable;
       }
   }
   
   sub menuitems_abbreviations {
       my %briefcats = (
                        text => 'pt',
                        links => 'p',
                        list => 'ps',
                        inline => 's',
                       );
       return %briefcats;
   }
   
   sub menuitems_categories {
       my @order = ('shown','text','links','list','inline');
       my %categories = (
                          shown => ['top','inline','foot','main'],
                          text  => ['name','role','crs','disc','fdbk'],
                          links => ['pers','logo','comm','roles','help','logout'],
                          list => ['about','prefs','port','wish','anno','rss'],
                          inline => ['cont','grades','chat','people','groups','resv','syll','feeds'],
                        );
       return (\@order,\%categories);
   }
   
   sub menuitems_titles {
       return &Apache::lonlocal::texthash (
           shown => 'Hierarchy',
           text  => 'Text',
           links => 'Header links',
           list => 'Drop-down list',
           inline => 'Inline links',
       );
   }
   
   sub menuitems_fields {
       return &Apache::lonlocal::texthash (
                  top => 'Display header',
                  inline => 'Display inline menu',
                  foot => 'Display footer',
                  main => 'Access to main menu',
                  pers => 'Personal',
                  logo => 'LON-CAPA',
                  comm => 'Messages',
                  roles => 'Roles/Courses',
                  help => 'Help',
                  logout => 'Logout',
                  name => 'Fullname',
                  crs => 'Course Title',
                  role => 'Current Role',
                  disc => 'Discussion',
                  fdbk => 'Feedback',
                  about => 'Information',
                  prefs => 'Preferences',
                  port => 'Portfolio',
                  wish => 'Stored Links',
                  anno => 'Calendar',
                  rss => 'RSS Feeds',
                  cont => 'Contents',
                  grades => 'Grades',
                  chat => 'Chat',
                  people => 'People',
                  groups => 'Groups',
                  resv => 'Reservations',
                  syll => 'Syllabus',
                  feeds => 'Feeds',
       );
   }
   
   sub menucollections_display {
       my ($collections) = @_;
       my %menu;
       my ($ordered,$cats) = &menuitems_categories();
       my @order = @{$ordered};
       my %categories = %{$cats};
       my %menutitles = &menuitems_titles();
       my %menufields = &menuitems_fields();
       foreach my $item (split(/;/,$collections)) {
           my ($num,$value) = split(/\%/,$item);
           if ($num =~ /^\d+$/) {
               my @entries = split(/\&/,$value);
               foreach my $entry (@entries) {
                   my ($name,$fields) = split(/=/,$entry);
                   $menu{$num}{$name} = $fields;
               }
           }
       }
       my $output = '';
       if (keys(%menu)) {
           my @current = sort { $a <=> $b } keys(%menu);
           foreach my $num (@current) {
               my %checked;
               foreach my $key (keys(%{$menu{$num}})) {
                   if (($key eq 'top') || ($key eq 'inline') || ($key eq 'foot') || ($key eq 'main')) {
                       if ($menu{$num}{$key} eq 'y') {
                           $checked{$key} = 1;
                       }
                   } else {
                       foreach my $field (split(/,/,$menu{$num}{$key})) {
                           if (exists($menufields{$field})) {
                               $checked{$field} = 1;
                           }
                       }
                   }
               }
               if (ref($menu{$num}) eq 'HASH') {
                   $output .= '<fieldset><legend>'.&mt('Collection [_1]',$num).'</legend>';
                   foreach my $category (@order) {
                       if ((ref($categories{$category}) eq 'ARRAY') && (@{$categories{$category}} > 0)) {
                           $output .= '<fieldset style="vertical-align:top; display:inline-block">'.
                                      '<legend>'.$menutitles{$category}.'</legend>'."\n";
                           if ($category eq 'text') {
                               $output .= '<b>'.&mt('Header Text').'</b><br /><br />';
                           }
                           foreach my $field (@{$categories{$category}}) {
                               if ($field eq 'disc') {
                                   $output .= '<br /><b>'.&mt('Footer Text').'</b><br /><br />';
                               }
                               if ($checked{$field}) {
                                   $output .= &Apache::lonhtmlcommon::confirm_success($menufields{$field});
                               } else {
                                   $output .= &Apache::lonhtmlcommon::confirm_success($menufields{$field},1);
                               }
                               $output .= '<br />';
                           }
                           $output .= '</fieldset>';
                       }
                   }
                   $output .= '</fieldset>';
               }
           }
       }
       return $output;
   }
   
   sub print_linkprotection {
       my ($cdom,$cnum,$settings,$rowtotal,$crstype,$noedit,$context) = @_;
   
       my %linkprotection;
       my $count = 0;
       my $next = 1;
       my ($datatable,$disabled,$css_class,$dest);
       if ($noedit) {
           $disabled = ' disabled="disabled"';
       }
       my %desc = &linkprot_names();
       my %lt = &Apache::lonlocal::texthash (
          'requ'      => 'Required settings',
          'opti'      => 'Optional settings',
       );
       my $itemcount = 0;
   
       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) eq 'HASH') && (ref($settings->{'linkprot'}) eq 'HASH')) {
           if (keys(%{$settings->{'linkprot'}})) {
               my @current = sort { $a <=> $b } keys(%{$settings->{'linkprot'}});
               $next += $current[-1];
               for (my $i=0; $i<@current; $i++) {
                   my $num = $current[$i];
                   my %values;
                   if (ref($settings->{'linkprot'}->{$num}) eq 'HASH') {
                       %values = %{$settings->{'linkprot'}->{$num}};
                   } else {
                       next;
                   }
                   my $selected;
                   if (($values{'version'} eq 'LTI-1p0') || ($values{'version'} eq '')) {
                       $selected = ' selected="selected"';
                   }
                   $css_class = $itemcount%2?' class="LC_odd_row"':'';
                   $datatable .=
                       '<tr '.$css_class.'><td><span class="LC_nobreak">'.
                       '<label><input type="checkbox" name="linkprot_del" value="'.$i.'"'.$disabled.' />'.
                       &mt('Delete?').'</label></span></td><td>';
                   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> '.
                       ('&nbsp;'x2).
                       '<span class="LC_nobreak">'.$desc{'version'}.':<select name="linkprot_version_'.$i.'"'.$disabled.'>'.
                       '<option value="LTI-1p0" '.$selected.'>1.1</option></select></span> '."\n".
                       ('&nbsp;'x2).
                       '<span class="LC_nobreak">'.$desc{'lifetime'}.':<input type="text" name="linkprot_lifetime_'.$i.'"'.
                       ' value="'.$values{'lifetime'}.'" size="3"'.$disabled.' /></span>';
                   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 '') {
                       $datatable .= '<span class="LC_nobreak">'.$desc{'key'};
                       if ($noedit) {
                           $datatable .= ': ['.&mt('not shown').']';
                       } elsif ($switchserver) {
                           $datatable .= ': ['.&mt('[_1] to view/edit',$switchserver).']';
                       } else {
                           $datatable .= ':<input type="text" size="25" name="linkprot_key_'.$i.'" value="'.$values{'key'}.'" autocomplete="off"'.$disabled.' />';
                       }
                       $datatable .= '</span> '.('&nbsp;'x2);
                   } elsif (!$switchserver) {
                       $datatable .= '<span class="LC_nobreak">'.$desc{'key'}.':'.
                                     '<input type="text" size="25" name="linkprot_key_'.$i.'" value="'.$values{'key'}.'" autocomplete="off"'.$disabled.' />'.
                                     '</span> '.('&nbsp;'x2);
                   }
                   if ($switchserver) {
                       if ($values{'usable'} ne '') {
                           $datatable .= '<div id="linkprot_divcurrsecret_'.$i.'" style="display:inline-block" /><span class="LC_nobreak">'.
                                         $desc{'secret'}.': ['.&mt('not shown').'] '.('&nbsp;'x2).'</span></div>'.
                                         '<span class="LC_nobreak">'.&mt('Change secret?').
                                         '<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).
                                         '<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 class="LC_nobreak"> - '.$switchmessage.'</span>'.
                                         '</div>';
                       } elsif ($values{'key'} eq '') {
                           $datatable .= '<span class="LC_nobreak">'.&mt('Key and Secret are required').' - '.$switchmessage.'</span>'."\n";
                       } else {
                           $datatable .= '<span class="LC_nobreak">'.&mt('Secret required').' - '.$switchmessage.'</span>'."\n";
                       }
                   } else {
                       if ($values{'usable'} ne '') {
                           $datatable .= '<div id="linkprot_divcurrsecret_'.$i.'" style="display:inline-block" /><span class="LC_nobreak">'.
                                         $desc{'secret'}.': ['.&mt('not shown').'] '.('&nbsp;'x2).'</span></div>'.
                                         '<span class="LC_nobreak">'.&mt('Change?').
                                         '<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).
                                         '<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" />'.
                                         '<span class="LC_nobreak">'.&mt('New Secret').':'.
                                         '<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>'.
                                         '<input type="hidden" name="linkprot_id_'.$i.'" value="'.$num.'" /></span></div>';
                       } else {
                           $datatable .=
                               '<span class="LC_nobreak">'.$desc{'secret'}.':'.
                               '<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>'.
                               '<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>';
                   $itemcount ++;
               }
           }
       }
       $css_class = $itemcount%2?' class="LC_odd_row"':'';
       $datatable .= '<tr '.$css_class.'><td><span class="LC_nobreak">'."\n".
                     '<input type="hidden" name="linkprot_maxnum" value="'.$next.'" />'."\n".
                     '<input type="checkbox" name="linkprot_add" value="1"'.$disabled.' />'.&mt('Add').'</span></td>'."\n".
                     '<td width="100%">';
       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".
                     ('&nbsp;'x2).
                     '<span class="LC_nobreak">'.$desc{'version'}.':<select name="linkprot_version_add"'.$disabled.'>'.
                     '<option value="LTI-1p0" selected="selected">1.1</option></select></span> '."\n".
                     ('&nbsp;'x2).
                     '<span class="LC_nobreak">'.$desc{'lifetime'}.':<input type="text" size="3" name="linkprot_lifetime_add" value="300"'.$disabled.' /></span> '."\n";
       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) {
           $datatable .= '<span class="LC_nobreak">'.&mt('Key and Secret are required').' - '.$switchmessage.'</span>'."\n";
       } else {
           $datatable .= '<span class="LC_nobreak">'.$desc{'key'}.':<input type="text" size="25" name="linkprot_key_add" value="" autocomplete="off"'.$disabled.' /></span> '."\n".
                         ('&nbsp;'x2).
                         '<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";
       }
       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>';
       $$rowtotal ++;
       return $datatable;
   }
   
   sub linkprot_names {
       return &Apache::lonlocal::texthash(
                                             'version'   => 'LTI Version',
                                             'key'       => 'Key',
                                             'lifetime'  => 'Nonce lifetime (s)',
                                             'name'      => 'Launcher Application',
                                             'secret'    => 'Secret',
                                             'requser'   => 'Use identity',
                                             'email'     => 'Email address',
                                             'sourcedid' => 'User ID',
                                             'other'     => 'Other',
                                             'auth'      => 'Display LON-CAPA login page',
                                             'reject'    => 'Discontinue launch process',
                                           );
   }
   
   sub check_switchserver {
       my ($cdom,$cnum,$context,$dest) = @_;
       my ($allowed,$switchserver,$home);
       if ($context eq 'domain') {
           $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();
           foreach my $id (@ids) { if ($id eq $home) { $allowed=1; } }
           if (!$allowed) {
               $switchserver='<a href="/adm/switchserver?otherserver='.$home.'&amp;role='.
                             &HTML::Entities::encode($env{'request.role'},'\'<>"&').
                             '&amp;destinationurl='.$dest.'">'.&mt('Switch Server').'</a>';
           }
       }
       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 4228  sub print_other { Line 5565  sub print_other {
                             input => 'textbox',                              input => 'textbox',
                             size  => '30',                              size  => '30',
                            };                             };
     my $output = &make_item_rows($cdom,\%items,\@ordered,$settings,$rowtotal,$crstype,'other',$noedit);      return &make_item_rows($cdom,\%items,\@ordered,$settings,$rowtotal,$crstype,'other',$noedit);
 }  }
   
 sub get_other_items {  sub get_other_items {
Line 4257  sub get_other_items { Line 5594  sub get_other_items {
 }  }
   
 sub item_table_row_start {  sub item_table_row_start {
     my ($text,$count,$add_class,$colspan) = @_;      my ($text,$count,$add_class,$colspan,$leftclass,$rightclass) = @_;
     my $output;      my $output;
     my $css_class = ($count % 2) ? 'LC_odd_row' : 'LC_even_row';      my $css_class = ($count % 2) ? 'LC_odd_row' : 'LC_even_row';
     $css_class = (join(' ',$css_class,$add_class)) unless ($add_class eq '');      $css_class = (join(' ',$css_class,$add_class)) unless ($add_class eq '');
       if ($leftclass eq '') {
           $leftclass = 'LC_left_item';
       }
       if ($rightclass eq '') {
           $rightclass = 'LC_right_item';
       }
     $output .= '<tr class="'.$css_class.'">'."\n".      $output .= '<tr class="'.$css_class.'">'."\n".
                '<td class="LC_left_item">'.$text.                 '<td class="'.$leftclass.'">'.$text.
                '</td>';                 '</td>';
     if ($colspan) {      if ($colspan > 1) {
         $output .= '<td class="LC_right_item" colspan="'.$colspan.'">';          $output .= '<td class="'.$rightclass.'" colspan="'.$colspan.'">';
     } else {      } else {
         $output .= '<td class="LC_right_item">';          $output .= '<td class="'.$rightclass.'">';
     }      }
     return $output;      return $output;
 }  }
Line 4308  sub yesno_radio { Line 5651  sub yesno_radio {
 }  }
   
 sub select_from_options {  sub select_from_options {
     my ($item,$order,$options,$curr,$nullval,$multiple,$maxsize,$onchange,$noedit) = @_;      my ($item,$order,$options,$curr,$nullval,$multiple,$maxsize,$onchange,$noedit,$id) = @_;
     my $output;      my $output;
     my $disabled;      my $disabled;
     if ($noedit) {      if ($noedit) {
Line 4324  sub select_from_options { Line 5667  sub select_from_options {
                 $output .= ' size="'.$maxsize.'"';                  $output .= ' size="'.$maxsize.'"';
             }              }
         }          }
           if ($id ne '') {
               $output .= ' id="'.$id.'"';
           }
         $output .= $disabled.'>'."\n";          $output .= $disabled.'>'."\n";
         if ($nullval ne '') {          if ($nullval ne '') {
             $output .= '<option value=""';              $output .= '<option value=""';
Line 4398  sub make_item_rows { Line 5744  sub make_item_rows {
                                                        $settings->{$item},$disabled);                                                         $settings->{$item},$disabled);
             } elsif ($items->{$item}{input} eq 'radio') {              } elsif ($items->{$item}{input} eq 'radio') {
                 my ($unsetdefault,$valueyes,$valueno);                  my ($unsetdefault,$valueyes,$valueno);
                 if (($item eq 'usejsme') || ($item eq 'uselcmath')) {                  if (($item eq 'usejsme') || ($item eq 'uselcmath') || ($item eq 'inline_chem')) {
                      my %domdefs = &Apache::lonnet::get_domain_defaults($cdom);                       my %domdefs = &Apache::lonnet::get_domain_defaults($cdom);
                      unless ($domdefs{$item} eq '0') {                       unless ($domdefs{$item} eq '0') {
                          $unsetdefault = 1;                           $unsetdefault = 1;
Line 4408  sub make_item_rows { Line 5754  sub make_item_rows {
                 }                  }
                 $datatable .= &yesno_radio($item,$settings,$unsetdefault,$valueyes,$valueno,$noedit);                  $datatable .= &yesno_radio($item,$settings,$unsetdefault,$valueyes,$valueno,$noedit);
             } elsif ($items->{$item}{input} eq 'selectbox') {              } elsif ($items->{$item}{input} eq 'selectbox') {
                   my $id;
                   if ($caller eq 'menuitems') {
                       $id = $item;
                   }
                 my $curr = $settings->{$item};                  my $curr = $settings->{$item};
                 $datatable .=                  $datatable .=
                     &select_from_options($item,$items->{$item}{'order'},                      &select_from_options($item,$items->{$item}{'order'},
                                          $items->{$item}{'options'},$curr,                                           $items->{$item}{'options'},$curr,
                                          $items->{$item}{'nullval'},                                           $items->{$item}{'nullval'},
                                          undef,undef,undef,$noedit);                                           undef,undef,undef,$noedit,$id);
             } elsif ($items->{$item}{input} eq 'textbox') {              } elsif ($items->{$item}{input} eq 'textbox') {
                 my $disabled;                  my $disabled;
                 if ($noedit) {                  if ($noedit) {

Removed from v.1.49.2.25  
changed lines
  Added in v.1.49.2.28.2.6


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