Diff for /loncom/interface/lonparmset.pm between versions 1.522.2.28.4.8 and 1.522.2.31

version 1.522.2.28.4.8, 2023/01/31 15:47:57 version 1.522.2.31, 2024/07/03 04:06:27
Line 321  use Apache::lonnavmaps; Line 321  use Apache::lonnavmaps;
 use Apache::longroup;  use Apache::longroup;
 use Apache::lonrss;  use Apache::lonrss;
 use HTML::Entities;  use HTML::Entities;
   use Text::Wrap();
 use LONCAPA qw(:DEFAULT :match);  use LONCAPA qw(:DEFAULT :match);
   
   
Line 767  sub valout { Line 768  sub valout {
         }          }
     } else {      } else {
         if ($type eq 'date_interval') {          if ($type eq 'date_interval') {
             my ($totalsecs,$donesuffix) = split(/_/,$value,2);              my ($sec,$min,$hour,$mday,$mon,$year)=gmtime($value);
             my ($usesdone,$donebuttontext,$proctor,$secretkey);  
             if ($donesuffix =~ /^done\:([^\:]+)\:(.*)$/) {  
                 $donebuttontext = $1;  
                 (undef,$proctor,$secretkey) = split(/_/,$2);  
                 $usesdone = 'done';  
             } elsif ($donesuffix =~ /^done(|_.+)$/) {  
                 $donebuttontext = &mt('Done');  
                 ($usesdone,$proctor,$secretkey) = split(/_/,$donesuffix);  
             }  
             my ($sec,$min,$hour,$mday,$mon,$year)=gmtime($totalsecs);  
             my @timer;              my @timer;
             $year=$year-70;              $year=$year-70;
             $mday--;              $mday--;
Line 810  sub valout { Line 801  sub valout {
                 push(@timer,&mt('[quant,_1,sec]',0));                  push(@timer,&mt('[quant,_1,sec]',0));
             }              }
             $result.=join(", ",@timer);              $result.=join(", ",@timer);
             if ($usesdone eq 'done') {  
                 if ($secretkey) {  
                     $result .= ' '.&mt('+ "[_1]" with proctor key: [_2]',$donebuttontext,$secretkey);  
                 } else {  
                     $result .= ' + "'.$donebuttontext.'"';  
                 }  
             }  
         } elsif (&isdateparm($type)) {          } elsif (&isdateparm($type)) {
             $result = &Apache::lonlocal::locallocaltime($value).              $result = &Apache::lonlocal::locallocaltime($value).
         &date_sanity_info($value);          &date_sanity_info($value);
Line 831  sub valout { Line 815  sub valout {
   
   
 sub plink {  sub plink {
     my ($type,$dis,$value,$marker,$return,$call,$extra)=@_;      my ($type,$dis,$value,$marker,$return,$call)=@_;
     my $winvalue=$value;      my $winvalue=$value;
     unless ($winvalue) {      unless ($winvalue) {
         if ((&isdateparm($type)) || (&is_specialstring($type))) {      if (&isdateparm($type)) {
             $winvalue=$env{'form.recent_'.$type};              $winvalue=$env{'form.recent_'.$type};
         } elsif ($type eq 'string_yesno') {  
             if ($env{'form.recent_string'} =~ /^(yes|no)$/i) {  
                 $winvalue=$env{'form.recent_string'};  
             }  
         } else {          } else {
             $winvalue=$env{'form.recent_'.(split(/\_/,$type))[0]};              $winvalue=$env{'form.recent_'.(split(/\_/,$type))[0]};
         }          }
Line 850  sub plink { Line 830  sub plink {
     my $valout = &valout($value,$type,1);      my $valout = &valout($value,$type,1);
     my $unencmarker = $marker;      my $unencmarker = $marker;
     foreach my $item (\$type, \$dis, \$winvalue, \$marker, \$return, \$call,      foreach my $item (\$type, \$dis, \$winvalue, \$marker, \$return, \$call,
               \$hour, \$min, \$sec, \$extra) {                \$hour, \$min, \$sec) {
     $$item = &HTML::Entities::encode($$item,'"<>&');      $$item = &HTML::Entities::encode($$item,'"<>&');
     $$item =~ s/\'/\\\'/g;      $$item =~ s/\'/\\\'/g;
     }      }
     return '<table width="100%"><tr valign="top" align="right"><td><a name="'.$unencmarker.'" /></td></tr><tr><td align="center">'.      return '<table width="100%"><tr valign="top" align="right"><td><a name="'.$unencmarker.'" /></td></tr><tr><td align="center">'.
     '<a href="javascript:pjump('."'".$type."','".$dis."','".$winvalue."','"      '<a href="javascript:pjump('."'".$type."','".$dis."','".$winvalue."','"
         .$marker."','".$return."','".$call."','".$hour."','".$min."','".$sec."','".$extra."'".');">'.          .$marker."','".$return."','".$call."','".$hour."','".$min."','".$sec."'".');">'.
         $valout.'</a></td></tr></table>';          $valout.'</a></td></tr></table>';
 }  }
   
Line 872  sub page_js { Line 852  sub page_js {
     $pjump_def      $pjump_def
   
     function psub() {      function psub() {
         var specstring = /^string_!(yesno|any)/i;  
         if (document.parmform.pres_marker.value!='') {          if (document.parmform.pres_marker.value!='') {
             document.parmform.action+='#'+document.parmform.pres_marker.value;              document.parmform.action+='#'+document.parmform.pres_marker.value;
             var typedef=new Array();              var typedef=new Array();
             typedef=document.parmform.pres_type.value.split('_');              typedef=document.parmform.pres_type.value.split('_');
             if (document.parmform.pres_type.value!='') {             if (document.parmform.pres_type.value!='') {
                 if ((typedef[0]=='date') ||              if (typedef[0]=='date') {
                     (specstring.test(document.parmform.pres_type.value))) {                  eval('document.parmform.recent_'+
                     eval('document.parmform.recent_'+                       document.parmform.pres_type.value+
                         document.parmform.pres_type.value+               '.value=document.parmform.pres_value.value;');
                         '.value=document.parmform.pres_value.value;');              } else {
                 } else {                  eval('document.parmform.recent_'+typedef[0]+
                     eval('document.parmform.recent_'+typedef[0]+               '.value=document.parmform.pres_value.value;');
                         '.value=document.parmform.pres_value.value;');  
                 }  
             }              }
          }
             document.parmform.submit();              document.parmform.submit();
         } else {          } else {
             document.parmform.pres_value.value='';              document.parmform.pres_value.value='';
Line 929  function showHide_courseContent() { Line 907  function showHide_courseContent() {
 COURSECONTENTSCRIPT  COURSECONTENTSCRIPT
 }  }
   
 sub validateparms_js {  
     return <<'ENDSCRIPT';  
   
 function validateParms() {  
     var textRegExp = /^settext_/;  
     var ipRegExp = /^setip/;  
     var ipallowRegExp = /^setipallow_/;  
     var ipdenyRegExp = /^setipdeny_/;  
     var deeplinkRegExp = /^deeplink_/;  
     var dlListScopeRegExp = /^deeplink_(state|others|listing|scope)_/;  
     var dlLinkProtectRegExp = /^deeplink_protect_/;  
     var dlLtidRegExp = /^deeplink_ltid_/;  
     var dlLticRegExp = /^deeplink_ltic_/;  
     var dlKeyRegExp = /^deeplink_key_/;  
     var dlMenusRegExp = /^deeplink_menus_/;  
     var dlCollsRegExp = /^deeplink_colls_/;  
     var dlTargetRegExp = /^deeplink_target_/;  
     var dlExitRegExp = /^deeplink_exit_/;  
     var dlExitTextRegExp = /^deeplink_exittext_/;  
     var patternIP = /[\[\]\*\.a-zA-Z\d\-]+/;  
     var numelements = document.parmform.elements.length;  
     if ((typeof(numelements) != 'undefined') && (numelements != null)) {  
         if (numelements) {  
             for (i=0; i<numelements; i++) {  
                 var name=document.parmform.elements[i].name;  
                 if (ipRegExp.test(name)) {  
                     if (ipallowRegExp.test(name)) {  
                         var identifier = name.replace(ipallowRegExp,'');  
                         var possallow = document.parmform.elements[i].value;  
                         possallow = possallow.replace(/^\s+|\s+$/g,'');  
                         if (patternIP.test(possallow)) {  
                             if (document.parmform.elements['set_'+identifier].value) {  
                                 possallow = ','+possallow;  
                             }  
                             document.parmform.elements['set_'+identifier].value += possallow;  
                         }  
                     } else if (ipdenyRegExp.test(name)) {  
                         var identifier = name.replace(ipdenyRegExp,'');  
                         var possdeny = document.parmform.elements[i].value;  
                         possdeny = possdeny.replace(/^\s+|\s+$/g,'');  
                         if (patternIP.test(possdeny)) {  
                             possdeny = '!'+possdeny;  
                             if (document.parmform.elements['set_'+identifier].value) {  
                                 possdeny = ','+possdeny;  
                             }  
                             document.parmform.elements['set_'+identifier].value += possdeny;  
                         }  
                     }  
                 } else if (deeplinkRegExp.test(name)) {  
                     if (dlListScopeRegExp.test(name)) {  
                         var identifier =  name.replace(dlListScopeRegExp,'');  
                         var idx = document.parmform.elements[i].selectedIndex;  
                         if (idx > 0) {  
                             var possdeeplink = document.parmform.elements[i].options[idx].value  
                             possdeeplink = possdeeplink.replace(/^\s+|\s+$/g,'');  
                             if (document.parmform.elements['set_'+identifier].value) {  
                                 possdeeplink = ','+possdeeplink;  
                             }  
                             document.parmform.elements['set_'+identifier].value += possdeeplink;  
                         }  
                     } else if (dlLinkProtectRegExp.test(name)) {  
                         if (document.parmform.elements[i].checked) {  
                             var identifier =  name.replace(dlLinkProtectRegExp,'');  
                             var posslinkurl = document.parmform.elements[i].value;  
                             posslinkurl = posslinkurl.replace(/^\s+|\s+$/g,'');  
                             if (document.parmform.elements['set_'+identifier].value) {  
                                 posslinkurl = ','+posslinkurl;  
                             }  
                             document.parmform.elements['set_'+identifier].value += posslinkurl;  
                         }  
                     } else if (dlLtidRegExp.test(name)) {  
                         var identifier = name.replace(dlLtidRegExp,'');  
                         if (isRadioSet('deeplink_protect_'+identifier,'ltid')) {  
                             var possltid = document.parmform.elements[i].value;  
                             possltid = possltid.replace(/\D+/g,'');  
                             if (possltid.length) {  
                                 if (document.parmform.elements['set_'+identifier].value) {  
                                     possltid = ':'+possltid;  
                                 }  
                                 document.parmform.elements['set_'+identifier].value += possltid;  
                             } else {  
                                 document.parmform.elements['set_'+identifier].value = '';  
                                 alert("A link type of 'domain LTI launch' was selected but no domain LTI launcher was selected.\nPlease select one, or choose a different supported link type.");  
                                 return false;  
                             }  
                         }  
                     } else if (dlLticRegExp.test(name)) {  
                         var identifier = name.replace(dlLticRegExp,'');  
                         if (isRadioSet('deeplink_protect_'+identifier,'ltic')) {  
                             var possltic = document.parmform.elements[i].value;  
                             possltic = possltic.replace(/\D+/g,'');  
                             if (possltic.length) {  
                                 if (document.parmform.elements['set_'+identifier].value) {  
                                     possltic = ':'+possltic;  
                                 }  
                                 document.parmform.elements['set_'+identifier].value += possltic;  
                             } else {  
                                 document.parmform.elements['set_'+identifier].value = '';  
                                 alert("A link type of 'course LTI launch' was selected but no course LTI launcher was selected.\nPlease select one, or choose a different supported link type.");  
                                 return false;  
                             }  
                         }  
                     } else if (dlKeyRegExp.test(name)) {  
                         var identifier = name.replace(dlKeyRegExp,'');  
                         if (isRadioSet('deeplink_protect_'+identifier,'key')) {  
                             var posskey = document.parmform.elements[i].value;  
                             posskey = posskey.replace(/^\s+|\s+$/g,'');  
                             var origlength = posskey.length;  
                             posskey = posskey.replace(/[^a-zA-Z\d_.!@#$%^&*()+=-]/g,'');  
                             var newlength = posskey.length;  
                             if (newlength > 0) {  
                                 var change = origlength - newlength;  
                                 if (change) {  
                                     alert(change+' disallowed character(s) removed from deeplink key');  
                                 }  
                                 if (document.parmform.elements['set_'+identifier].value) {  
                                     posskey = ':'+posskey;  
                                 }  
                                 document.parmform.elements['set_'+identifier].value += posskey;  
                             } else {  
                                 document.parmform.elements['set_'+identifier].value = '';  
                                 if (newlength < origlength) {  
                                     alert("A link type of 'deep with key' was selected but the key value was blank, after removing disallowed characters.\nPlease enter a key using one or more of: a-zA-Z0-9_.!@#$%^&*()+=-");  
                                 } else {  
                                     alert("A link type of 'deep with key' was selected but the key value was blank.\nPlease enter a key.");  
                                 }  
                                 return false;  
                             }  
                         }  
                     } else if (dlMenusRegExp.test(name)) {  
                         if (document.parmform.elements[i].checked) {  
                             var identifier =  name.replace(dlMenusRegExp,'');  
                             var posslinkmenu = document.parmform.elements[i].value;  
                             posslinkmenu = posslinkmenu.replace(/^\s+|\s+$/g,'');  
                             if (posslinkmenu == 'std') {  
                                 posslinkmenu = '0';  
                                 if (document.parmform.elements['set_'+identifier].value) {  
                                     posslinkmenu = ','+posslinkmenu;  
                                 }  
                                 document.parmform.elements['set_'+identifier].value += posslinkmenu;  
                             }  
                         }  
                     } else if (dlCollsRegExp.test(name)) {  
                         var identifier =  name.replace(dlCollsRegExp,'');  
                         if (isRadioSet('deeplink_menus_'+identifier,'colls')) {  
                             var posslinkmenu = document.parmform.elements[i].value;  
                             if (document.parmform.elements['set_'+identifier].value) {  
                                 posslinkmenu = ','+posslinkmenu;  
                             }  
                             document.parmform.elements['set_'+identifier].value += posslinkmenu;  
                         }  
                     } else if (dlTargetRegExp.test(name)) {  
                         var identifier =  name.replace(dlTargetRegExp,'');  
                         var idx = document.parmform.elements[i].selectedIndex;  
                         if (idx > 0) {  
                             var linktarget = document.parmform.elements[i].options[idx].value  
                             linktarget = linktarget.replace(/^\s+|\s+$/g,'');  
                             if (document.parmform.elements['set_'+identifier].value) {  
                                 linktarget = ','+linktarget;  
                             }  
                             document.parmform.elements['set_'+identifier].value += linktarget;  
                         }  
                     } else if (dlExitRegExp.test(name)) {  
                         if (document.parmform.elements[i].checked) {  
                             var identifier =  name.replace(dlExitRegExp,'');  
                             var posslinkexit = document.parmform.elements[i].value;  
                             posslinkexit = posslinkexit.replace(/^\s+|\s+$/g,'');  
                             if (document.parmform.elements['set_'+identifier].value) {  
                                 posslinkexit = ','+posslinkexit;  
                             }  
                             document.parmform.elements['set_'+identifier].value += posslinkexit;  
                         }  
                     } else if (dlExitTextRegExp.test(name)) {  
                         var identifier = name.replace(dlExitTextRegExp,'');  
                         if ((isRadioSet('deeplink_exit_'+identifier,'yes')) ||  
                             (isRadioSet('deeplink_exit_'+identifier,'url'))) {  
                             var posstext = document.parmform.elements[i].value;  
                             posstext = posstext.replace(/^\s+|\s+$/g,'');  
                             var origlength = posstext.length;  
                             posstext = posstext.replace(/[:;'",]/g,'');  
                             var newlength = posstext.length;  
                             if (newlength > 0) {  
                                 var change = origlength - newlength;  
                                 if (change) {  
                                     alert(change+' disallowed character(s) removed from Exit Button text');  
                                 }  
                                 if (posstext !== 'Exit Tool') {  
                                     posstext = ':'+posstext;  
                                     document.parmform.elements['set_'+identifier].value += posstext;  
                                 }  
                             } else {  
                                 document.parmform.elements['set_'+identifier].value = '';  
                                 if (newlength < origlength) {  
                                     alert("An exit link type of 'In use' was selected but the button text value was blank, after removing disallowed characters.\nDisallowed characters are ,\":;'");  
                                 } else {  
                                     alert("An exit link type of 'In use' was selected but the button text value was blank.\nPlease enter the text to use.");  
                                 }  
                                 return false;  
                             }  
                         }  
                     }  
                 }  
             }  
         }  
     }  
     return true;  
 }  
   
 function isRadioSet(name,expected) {  
     var menuitems = document.getElementsByName(name);  
     var radioLength = menuitems.length;  
     result = false;  
     if (radioLength  > 1) {  
         for (var j=0; j<radioLength; j++) {  
             if (menuitems[j].checked) {  
                 if (menuitems[j].value == expected) {  
                     result = true;  
                     break;  
                 }  
             }  
         }  
     }  
     return result;  
 }  
   
 ENDSCRIPT  
 }  
   
 # Javascript initialization, for overview mode  
 sub ipacc_boxes_js  {  
     my $remove = &mt('Remove');  
     return <<"END";  
 \$(document).ready(function() {  
     var wrapper         = \$(".LC_string_ipacc_wrap");  
     var add_button      = \$(".LC_add_ipacc_button");  
     var ipaccRegExp     = /^LC_string_ipacc_/;  
   
     \$(add_button).click(function(e){  
         e.preventDefault();  
         var identifier = \$(this).closest("div").attr("id");  
         identifier = identifier.replace(ipaccRegExp,'');  
         \$(this).closest('div').find('.LC_string_ipacc_inner').append('<div><input type="text" name="setip'+identifier+'" /><a href="#" class="LC_remove_ipacc">$remove</a></div>');  
     });  
   
     \$(wrapper).delegate(".LC_remove_ipacc","click", function(e){  
         e.preventDefault(); \$(this).closest("div").remove();  
     })  
 });  
   
   
 END  
 }  
   
 sub done_proctor_js {  
     my $defaultdone = &mt('Done');  
     &js_escape(\$defaultdone);  
     return <<"END";  
 function toggleSecret(form,radio,key) {  
     var radios = form[radio+key];  
     if (radios.length) {  
         for (var i=0; i<radios.length; i++) {  
             if (radios[i].checked) {  
                 if (radios[i].value == '_done_proctor') {  
                     if (document.getElementById('done_'+key+'_proctorkey')) {  
                         document.getElementById('done_'+key+'_proctorkey').type='text';  
                     }  
                 } else {  
                     if (document.getElementById('done_'+key+'_proctorkey')) {  
                         document.getElementById('done_'+key+'_proctorkey').type='hidden';  
                         document.getElementById('done_'+key+'_proctorkey').value='';  
                     }  
                 }  
                 if (document.getElementById('done_'+key+'_buttontext')) {  
                     if (radios[i].value == '') {  
                         document.getElementById('done_'+key+'_buttontext').value = '';  
                     } else {  
                         if (document.getElementById('done_'+key+'_buttontext').value == '') {  
                             document.getElementById('done_'+key+'_buttontext').value = '$defaultdone';  
                         }  
                     }  
                 }  
             }  
         }  
     }  
 }  
 END  
   
 }  
   
 # Javascript function toggle  
 sub deeplink_js {  
     return <<"END";  
 function toggleDeepLink(form,item,key) {  
     var radios = form['deeplink_'+item+'_'+key];  
     if (radios.length) {  
         var keybox;  
         if (document.getElementById('deeplink_key_'+item+'_'+key)) {  
             keybox = document.getElementById('deeplink_key_'+item+'_'+key);  
         }  
         var divoptions = new Array();  
         if (item == 'protect') {  
             divoptions = ['ltic','ltid'];  
         } else {  
             if (item == 'menus') {  
                 divoptions = ['colls'];  
             }  
         }  
         var seldivs = new Array();  
         if ((item == 'protect') || (item == 'menus')) {  
             for (var i=0; i<divoptions.length; i++) {  
                 if (document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key)) {  
                     seldivs[i] = document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key);  
                 } else {  
                     seldivs[i] = '';  
                 }  
             }  
         }  
         for (var i=0; i<radios.length; i++) {  
             if (radios[i].checked) {  
                 if ((item == 'protect') || (item == 'menus')) {  
                     for (var j=0; j<seldivs.length; j++) {  
                         if (radios[i].value == divoptions[j]) {  
                             if (seldivs[j] != '') {  
                                 seldivs[j].style.display = 'inline-block';  
                             }  
                             if (item == 'protect') {  
                                 keybox.type = 'hidden';  
                                 keybox.value = '';  
                             }  
                         } else {  
                             if (seldivs[j] != '') {  
                                 seldivs[j].style.display = 'none';  
                                 form['deeplink_'+divoptions[j]+'_'+key].selectedIndex = 0;  
                             }  
                         }  
                     }  
                     if (item == 'protect') {  
                         if (radios[i].value == 'key') {  
                             keybox.type = 'text';  
                         } else {  
                             keybox.type = 'hidden';  
                         }  
                     }  
                 } else if (item == 'exit') {  
                     if (document.getElementById('deeplinkdiv_'+item+'_'+key)) {  
                         if (radios[i].value == 'no') {  
                             document.getElementById('deeplinkdiv_'+item+'_'+key).style.display = 'none';  
                             if (document.getElementById('deeplink_exittext_'+key)) {  
                                 if (document.getElementById('deeplink_exittext_'+key).value != '') {  
                                     document.getElementById('deeplink_exittext_'+key).value = '';  
                                 }  
                             }  
                         } else {  
                             document.getElementById('deeplinkdiv_'+item+'_'+key).style.display = 'inline-block';  
                             if (document.getElementById('deeplink_exittext_'+key)) {  
                                 if (document.getElementById('deeplink_exittext_'+key).value == '') {  
                                     document.getElementById('deeplink_exittext_'+key).value = 'Exit Tool';  
                                 }  
                             }  
                         }  
                     }  
                 }  
             }  
         }  
     }  
 }  
 END  
   
 }  
   
 sub startpage {  sub startpage {
     my ($r,$psymb) = @_;      my ($r,$psymb) = @_;
   
Line 1388  sub print_row { Line 996  sub print_row {
     my $thismarker=$which;      my $thismarker=$which;
     $thismarker=~s/^parameter\_//;      $thismarker=~s/^parameter\_//;
     my $mprefix=$rid.'&'.$thismarker.'&';      my $mprefix=$rid.'&'.$thismarker.'&';
     my ($parmname)=($thismarker=~/\_([^\_]+)$/);  
     my $effective_parm = &valout($outpar[$result],$typeoutpar[$result]);      my $effective_parm = &valout($outpar[$result],$typeoutpar[$result]);
     my ($othergrp,$grp_parm,$controlgrp,$extra);      my ($othergrp,$grp_parm,$controlgrp);
   
     if ($parmname eq 'deeplink') {  
         my ($domltistr,$crsltistr);  
         my %lti =  
             &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},  
                                             'linkprot');  
         if (keys(%lti)) {  
             foreach my $item (sort { $a <=> $b }  (keys(%lti))) {  
                 if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) {  
                     $domltistr .= $item.':'.&escape(&escape($lti{$item}{'name'})).',';  
                 }  
             }  
             $domltistr =~ s/,$//;  
             if ($domltistr) {  
                 $extra = 'ltid_'.$domltistr;  
             }  
         }  
         my %courselti = &Apache::lonnet::get_course_lti($cnum,$cdom);  
         if (keys(%courselti)) {  
             foreach my $item (sort { $a <=> $b } keys(%courselti)) {  
                 if (($item =~ /^\d+$/) && (ref($courselti{$item}) eq 'HASH')) {  
                     $crsltistr .= $item.':'.&escape(&escape($courselti{$item}{'name'})).',';  
                 }  
             }  
             $crsltistr =~ s/,$//;  
             if ($crsltistr) {  
                 if ($extra) {  
                     $extra .= '&';  
                 }  
                 $extra .= 'ltic_'.$crsltistr;  
             }  
         }  
         if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {  
             my @colls;  
             foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {  
                 my ($num,$value) = split(/\%/,$item);  
                 if ($num =~ /^\d+$/) {  
                     push(@colls,$num);  
                 }  
             }  
             if (@colls) {  
                 if ($extra) {  
                     $extra .= '&';  
                 }  
                 $extra .= 'menus_'.join(',',@colls);  
             }  
         }  
     }  
     if ($parmlev eq 'general') {      if ($parmlev eq 'general') {
   
         if ($uname) {          if ($uname) {
             &print_td($r,3,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly,$extra);              &print_td($r,3,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly);
         } elsif ($cgroup) {          } elsif ($cgroup) {
             &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,$noeditgrp,$readonly,$extra);              &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,$noeditgrp,$readonly);
         } elsif ($csec) {          } elsif ($csec) {
             &print_td($r,9,$defbgtwo,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly,$extra);              &print_td($r,9,$defbgtwo,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly);
         } else {          } else {
             &print_td($r,14,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly,$extra);              &print_td($r,14,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly);
         }          }
     } elsif ($parmlev eq 'map') {      } elsif ($parmlev eq 'map') {
   
         if ($uname) {          if ($uname) {
             &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly,$extra);              &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly);
         } elsif ($cgroup) {          } elsif ($cgroup) {
             &print_td($r,5,$defbgthree,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,$noeditgrp,$readonly,$extra);              &print_td($r,5,$defbgthree,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,$noeditgrp,$readonly);
         } elsif ($csec) {          } elsif ($csec) {
             &print_td($r,8,$defbgtwo,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly,$extra);              &print_td($r,8,$defbgtwo,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly);
         } else {          } else {
             &print_td($r,13,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly,$extra);              &print_td($r,13,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly);
         }          }
     } else {      } else {
         if ($uname) {          if ($uname) {
Line 1479  sub print_row { Line 1039  sub print_row {
             }              }
         }          }
   
         &print_td($r,14,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly,$extra);          &print_td($r,14,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly);
   
     &print_td($r,13,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly,$extra);      &print_td($r,13,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly);
     &print_td($r,12,'#FFDDDD',$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly,$extra);      &print_td($r,12,'#FFDDDD',$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly);
     &print_td($r,11,'#FFDDDD',$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly,$extra);      &print_td($r,11,'#FFDDDD',$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly);
     &print_td($r,10,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly,$extra);      &print_td($r,10,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly);
   
     if ($csec) {      if ($csec) {
         &print_td($r,9,$defbgtwo,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly,$extra);          &print_td($r,9,$defbgtwo,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly);
         &print_td($r,8,$defbgtwo,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly,$extra);          &print_td($r,8,$defbgtwo,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly);
         &print_td($r,7,$defbgtwo,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly,$extra);          &print_td($r,7,$defbgtwo,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly);
     }      }
   
         if ($cgroup) {          if ($cgroup) {
             &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,$noeditgrp,$readonly,$extra);              &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,$noeditgrp,$readonly);
             &print_td($r,5,$defbgthree,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,$noeditgrp,$readonly,$extra);              &print_td($r,5,$defbgthree,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,$noeditgrp,$readonly);
             &print_td($r,4,$defbgthree,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,$noeditgrp,$readonly,$extra);              &print_td($r,4,$defbgthree,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,$noeditgrp,$readonly);
         }          }
   
     if ($uname) {      if ($uname) {
             if ($othergrp) {              if ($othergrp) {
                 $r->print($othergrp);                  $r->print($othergrp);
             }              }
         &print_td($r,3,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly,$extra);          &print_td($r,3,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly);
         &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly,$extra);          &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly);
         &print_td($r,1,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly,$extra);          &print_td($r,1,$defbgone,$result,\@outpar,$mprefix,$_,\@typeoutpar,$display,'',$readonly);
     }      }
   
     } # end of $parmlev if/else      } # end of $parmlev if/else
Line 1524  sub print_row { Line 1084  sub print_row {
 }  }
   
 sub print_td {  sub print_td {
     my ($r,$which,$defbg,$result,$outpar,$mprefix,$value,$typeoutpar,$display,$noeditgrp,$readonly,$extra)=@_;      my ($r,$which,$defbg,$result,$outpar,$mprefix,$value,$typeoutpar,$display,$noeditgrp,$readonly)=@_;
     $r->print('<td style="background-color:'.(($result==$which)?'#AAFFAA':$defbg).      $r->print('<td style="background-color:'.(($result==$which)?'#AAFFAA':$defbg).
               ';" align="center">');                ';" align="center">');
     my $nolink = 0;      my $nolink = 0;
Line 1552  sub print_td { Line 1112  sub print_td {
     } else {      } else {
         $r->print(&plink($$typeoutpar[$which],          $r->print(&plink($$typeoutpar[$which],
                          $$display{$value},$$outpar[$which],                           $$display{$value},$$outpar[$which],
                          $mprefix."$which",'parmform.pres','psub',$extra));                           $mprefix."$which",'parmform.pres','psub'));
     }      }
     $r->print('</td>'."\n");      $r->print('</td>'."\n");
 }  }
Line 1718  sub isdateparm { Line 1278  sub isdateparm {
     return (($type=~/^date/) && (!($type eq 'date_interval')));      return (($type=~/^date/) && (!($type eq 'date_interval')));
 }  }
   
 # Determine if parameter type is specialized string type (i.e.,  
 # not just string or string_yesno.  
   
 sub is_specialstring {  
     my $type=shift;  
     return (($type=~/^string_/) && ($type ne 'string_yesno'));  
 }  
   
 #  #
 # parmmenu displays a list of the selected parameters.  # parmmenu displays a list of the selected parameters.
 # It also offers a link to show/hide the complete parameter list  # It also offers a link to show/hide the complete parameter list
Line 1860  sub lookUpTableParameter { Line 1412  sub lookUpTableParameter {
         'buttonshide' => 'hiding',          'buttonshide' => 'hiding',
         'turnoffeditor' => 'hiding',          'turnoffeditor' => 'hiding',
         'encrypturl' => 'hiding',          'encrypturl' => 'hiding',
         'deeplink' => 'hiding',  
         'randomorder' => 'high_level_randomization',          'randomorder' => 'high_level_randomization',
         'randompick' => 'high_level_randomization',          'randompick' => 'high_level_randomization',
         'available' => 'slots',          'available' => 'slots',
Line 1949  sub parmboxes { Line 1500  sub parmboxes {
         &whatIsMyCategory($tempparameter, \%categoryList);          &whatIsMyCategory($tempparameter, \%categoryList);
     }      }
     #part to print the parm-list      #part to print the parm-list
       $Text::Wrap::columns=60;
       $Text::Wrap::separator='<br />';
     $r->print('<div class="LC_columnSection">'."\n");      $r->print('<div class="LC_columnSection">'."\n");
   
     #Print parameters      #Print parameters
Line 1966  sub parmboxes { Line 1519  sub parmboxes {
             if ($$pscat[0] eq "all" || grep $_ eq $tempkey, @{$pscat}) {              if ($$pscat[0] eq "all" || grep $_ eq $tempkey, @{$pscat}) {
                 $r->print(' checked="checked"');                  $r->print(' checked="checked"');
             }              }
             $r->print(' />'.($$allparms{$tempkey}=~/\S/ ? $$allparms{$tempkey}              $r->print(' />'.($$allparms{$tempkey}=~/\S/ ?
                                                       : $tempkey)                               Text::Wrap::wrap('','&nbsp;'x4,$$allparms{$tempkey})
                                : $tempkey)
                      .'</label></span><br />'."\n");                       .'</label></span><br />'."\n");
         }          }
         $r->print("</div>\n");          $r->print("</div>\n");
Line 2137  function group_or_section(caller) { Line 1691  function group_or_section(caller) {
     }      }
   
     if (%grouphash) {      if (%grouphash) {
         $groups=&mt('Group').': <select name="cgroup"';          $groups=&mt('Group:').' <select name="cgroup"';
         if (%sectionhash && $env{'form.action'} eq 'settable' && $currsec eq '') {          if (%sectionhash && $env{'form.action'} eq 'settable' && $currsec eq '') {
             $groups .= qq| onchange="group_or_section('cgroup')" |;              $groups .= qq| onchange="group_or_section('cgroup')" |;
         }          }
Line 2656  sub assessparms { Line 2210  sub assessparms {
                             foreach my $role (@possroles) {                              foreach my $role (@possroles) {
                                 if (ref($sections_by_role{$role}) eq 'ARRAY') {                                  if (ref($sections_by_role{$role}) eq 'ARRAY') {
                                     my @secs = sort { $a <=> $b } @{$sections_by_role{$role}};                                      my @secs = sort { $a <=> $b } @{$sections_by_role{$role}};
                                     $csec = $secs[0];                                      $csec = $secs[0]; 
                                     last;                                      last;
                                 }                                  }
                             }                              }
Line 2700  sub assessparms { Line 2254  sub assessparms {
                                          $uname,$udom);                                           $uname,$udom);
                     }                      }
                     $message .= '</span>';                      $message .= '</span>';
                     $uname='';                      $uname=''; 
                     if ($env{'request.course.sec'} ne '') {                      if ($env{'request.course.sec'} ne '') {
                         $csec=$env{'request.course.sec'};                          $csec=$env{'request.course.sec'};
                     } else {                      } else {
Line 2882  sub assessparms { Line 2436  sub assessparms {
   
     &startpage($r,$pssymb);      &startpage($r,$pssymb);
   
     foreach my $item ('tolerance','date_default','date_start','date_end',      foreach ('tolerance','date_default','date_start','date_end',
                       'date_interval','int','float','string','string_lenient',          'date_interval','int','float','string') {
                       'string_examcode','string_deeplink','string_discussvote',  
                       'string_useslots','string_problemstatus','string_ip',  
                       'string_questiontype') {  
         $r->print('<input type="hidden" value="'.          $r->print('<input type="hidden" value="'.
           &HTML::Entities::encode($env{'form.recent_'.$item},'"&<>').            &HTML::Entities::encode($env{'form.recent_'.$_},'"&<>').
           '" name="recent_'.$item.'" />');            '" name="recent_'.$_.'" />');
     }      }
   
     # ----- Start Parameter Selection      # ----- Start Parameter Selection
   
     # Hide parm selection and possibly table?      # Hide parm selection?
     my ($tablejs,$tabledivsty);  
     if (((($env{'form.uname'} ne '') || ($env{'form.id'} ne '')) && ($uname eq '')) &&  
         ($env{'form.dis'}) && ($pssymb eq '')) {  
         $tablejs = 'document.getElementById('."'parmtable'".').style.display = "";';  
         $tabledivsty = ' style="display:none"';  
     }  
     $r->print(<<ENDPARMSELSCRIPT);      $r->print(<<ENDPARMSELSCRIPT);
 <script type="text/javascript">  <script type="text/javascript">
 // <![CDATA[  // <![CDATA[
 function parmsel_show() {  function parmsel_show() {
   document.getElementById('parmsel').style.display = "";    document.getElementById('parmsel').style.display = "";
   document.getElementById('parmsellink').style.display = "none";    document.getElementById('parmsellink').style.display = "none";
   $tablejs  
 }  }
 // ]]>  // ]]>
 </script>  </script>
Line 3019  ENDPARMSELSCRIPT Line 2563  ENDPARMSELSCRIPT
         if ($parm_permission->{'edit'}) {          if ($parm_permission->{'edit'}) {
             undef($readonly);              undef($readonly);
         }          }
         $r->print('<div id="parmtable"'.$tabledivsty.'>');  
   
         if ($parmlev eq 'full') {          if ($parmlev eq 'full') {
 #  #
Line 3428  ENDMAPONE Line 2971  ENDMAPONE
                      .'</center>'                       .'</center>'
             );              );
         } # end of $parmlev eq general          } # end of $parmlev eq general
         $r->print('</div>');  
     }      }
     $r->print('</form>');      $r->print('</form>');
     $r->print(&Apache::loncommon::end_page());      $r->print(&Apache::loncommon::end_page());
Line 3510  sub storedata { Line 3052  sub storedata {
     if ($key =~ /^form\.([a-z]+)\_(.+)$/) {      if ($key =~ /^form\.([a-z]+)\_(.+)$/) {
         my $cmd=$1;          my $cmd=$1;
         my $thiskey=$2;          my $thiskey=$2;
         next if ($cmd eq 'setipallow' || $cmd eq 'setipdeny' || $cmd eq 'setdeeplink');  
         my ($tuname,$tudom)=&extractuser($thiskey);          my ($tuname,$tudom)=&extractuser($thiskey);
         my $tkey=$thiskey;          my $tkey=$thiskey;
             if ($tuname) {              if ($tuname) {
         $tkey=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;          $tkey=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
         }          }
         if ($cmd eq 'set' || $cmd eq 'datepointer' || $cmd eq 'dateinterval') {          if ($cmd eq 'set' || $cmd eq 'datepointer' || $cmd eq 'dateinterval') {
         my ($data, $typeof, $text, $name, $valchk, $valmatch, $namematch);          my ($data, $typeof, $text, $name, $valchk);
         if ($cmd eq 'set') {          if ($cmd eq 'set') {
             $data=$env{$key};              $data=$env{$key};
             $valmatch = '';  
             $valchk = $data;              $valchk = $data;
             $typeof=$env{'form.typeof_'.$thiskey};              $typeof=$env{'form.typeof_'.$thiskey};
             $text = &mt('Saved modified parameter for');              $text = &mt('Saved modified parameter for');
             if ($typeof eq 'string_questiontype') {              if ($typeof eq 'string_questiontype') {
                 $name = 'type';                  $name = 'type';
             } elsif ($typeof eq 'string_deeplink') {  
                 ($name) = ($typeof =~ /^string_(deeplink)$/);  
                 my $stringmatch = &standard_string_matches($typeof);  
                 if (ref($stringmatch) eq 'ARRAY') {  
                     foreach my $item (@{$stringmatch}) {  
                         if (ref($item) eq 'ARRAY') {  
                             my ($regexpname,$pattern) = @{$item};  
                             if ($pattern ne '') {  
                                 if ($data =~ /$pattern/) {  
                                     $valmatch = $regexpname;  
                                     $valchk = '';  
                                     last;  
                                 }  
                             }  
                         }  
                     }  
                 }  
             } elsif ($typeof eq 'string_lenient') {              } elsif ($typeof eq 'string_lenient') {
                 $name = 'lenient';                  $name = 'lenient';
             } elsif ($typeof eq 'string_discussvote') {              } elsif ($typeof eq 'string_discussvote') {
Line 3870  sub listdata { Line 3393  sub listdata {
               );                );
             }              }
         } elsif ($thistype eq 'date_interval') {          } elsif ($thistype eq 'date_interval') {
             $r->print(&date_interval_selector($thiskey,$name,              $r->print(&date_interval_selector($thiskey,
                       $$resourcedata{$thiskey},$readonly));                        $$resourcedata{$thiskey},$readonly));
         } elsif ($thistype =~ m/^string/) {          } elsif ($thistype =~ m/^string/) {
             if ($name eq 'availablestudent') {              if ($name eq 'availablestudent') {
Line 3893  sub listdata { Line 3416  sub listdata {
   
   
 sub date_interval_selector {  sub date_interval_selector {
     my ($thiskey, $pname, $showval, $readonly) = @_;      my ($thiskey, $showval, $readonly) = @_;
     my ($result,%skipval);      my $result;
     my $currval = $showval;      my $currval = $showval;
     foreach my $which (['days', 86400, 31],      foreach my $which (['days', 86400, 31],
                ['hours', 3600, 23],                 ['hours', 3600, 23],
                ['minutes', 60, 59],                 ['minutes', 60, 59],
                ['seconds',  1, 59]) {                 ['seconds',  1, 59]) {
     my ($name, $factor, $max) = @{ $which };          my ($name, $factor, $max) = @{ $which };
     my $amount = int($showval/$factor);          my $amount = int($showval/$factor);
     $showval  %= $factor;          $showval  %= $factor;
     my %select = ((map {$_ => $_} (0..$max)),          my %select = ((map {$_ => $_} (0..$max)),
               'select_form_order' => [0..$max]);                        'select_form_order' => [0..$max]);
     if ($currval eq '') {          if ($currval eq '') {
         unshift(@{$select{'select_form_order'}},'');              unshift(@{$select{'select_form_order'}},'');
         $select{''} = '';              $select{''} = '';
         $amount = '';              $amount = '';
     }          }
     $result .= &Apache::loncommon::select_form($amount,$name.'_'.$thiskey,          $result .= &Apache::loncommon::select_form($amount,$name.'_'.$thiskey,
                            \%select,'',$readonly);                                                     \%select,'',$readonly);
     $result .= ' '.&mt($name);          $result .= ' '.&mt($name);
     }  
     if ($pname eq 'interval') {  
         unless ($skipval{'done'}) {  
             my $checkedon = '';  
             my $checkedoff = '';  
             my $checkedproc = '';  
             my $currproctorkey = '';  
             my $currprocdisplay = 'hidden';  
             my $currdonetext = &mt('Done');  
             my $checkedoff = ' checked="checked"';  
             if ($currval =~ /^(?:\d+)_done$/) {  
                 $checkedon = ' checked="checked"';  
             } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:$/) {  
                 $currdonetext = $1;  
                 $checkedon = ' checked="checked"';  
             } elsif ($currval =~ /^(?:\d+)_done_proctor_(.+)$/) {  
                 $currproctorkey = $1;  
                 $checkedproc = ' checked="checked"';  
                 $currprocdisplay = 'text';  
             } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:_proctor_(.+)$/) {  
                 $currdonetext = $1;  
                 $currproctorkey = $2;  
                 $checkedproc = ' checked="checked"';  
                 $currprocdisplay = 'text';  
             } elsif ($currval ne '') {  
                 $checkedoff = ' checked="checked"';  
             } else {  
                 $currdonetext = '';  
             }  
             my $onclick = ' onclick="toggleSecret(this.form,'."'done_','$thiskey'".');"';  
             my $disabled;  
             if ($readonly) {  
                 $disabled = ' disabled="disabled"';  
             }  
             $result .= '<br /><span class="LC_nobreak">'.&mt('Include "done" button').  
                        '<label><input type="radio" value="" name="done_'.$thiskey.'"'.$checkedoff.$onclick.$disabled.' />'.  
                        &mt('No').'</label>'.('&nbsp;'x2).  
                        '<label><input type="radio" value="_done" name="done_'.$thiskey.'"'.$checkedon.$onclick.$disabled.' />'.  
                        &mt('Yes').'</label>'.('&nbsp;'x2).  
                        '<label><input type="radio" value="_done_proctor" name="done_'.$thiskey.'"'.$checkedproc.$onclick.$disabled.' />'.  
                        &mt('Yes, with proctor key').'</label>'.  
                        '<input type="'.$currprocdisplay.'" id="done_'.$thiskey.'_proctorkey" '.  
                        'name="done_'.$thiskey.'_proctorkey" value="'.&HTML::Entities::encode($currproctorkey,'"<>&').'"'.$disabled.' /></span><br />'.  
                        '<span class="LC_nobreak">'.&mt('Button text').': '.  
                        '<input type="text" name="done_'.$thiskey.'_buttontext" value="'.  
                        &HTML::Entities::encode($currdonetext,'"<>&').'"'.$disabled.' /></span>';  
         }  
     }      }
     unless ($readonly) {      unless ($readonly) {
         $result .= '<input type="hidden" name="dateinterval_'.$thiskey.'" />';          $result .= '<input type="hidden" name="dateinterval_'.$thiskey.'" />';
Line 3976  sub get_date_interval_from_form { Line 3452  sub get_date_interval_from_form {
                ['hours', 3600],                 ['hours', 3600],
                ['minutes', 60],                 ['minutes', 60],
                ['seconds',  1]) {                 ['seconds',  1]) {
     my ($name, $factor) = @{ $which };          my ($name, $factor) = @{ $which };
     if (defined($env{'form.'.$name.'_'.$key})) {          if (defined($env{'form.'.$name.'_'.$key})) {
         unless ($env{'form.'.$name.'_'.$key} eq '') {              unless ($env{'form.'.$name.'_'.$key} eq '') {
             $numnotnull ++;                  $numnotnull ++;
             $seconds += $env{'form.'.$name.'_'.$key} * $factor;                  $seconds += $env{'form.'.$name.'_'.$key} * $factor;
         }  
     }  
     }  
     if (($key =~ /\.interval$/) &&  
             (($env{'form.done_'.$key} eq '_done') || ($env{'form.done_'.$key} eq '_done_proctor'))) {  
         if ($env{'form.done_'.$key.'_buttontext'}) {  
             $env{'form.done_'.$key.'_buttontext'} =~ s/\://g;  
             $seconds .= '_done:'.$env{'form.done_'.$key.'_buttontext'}.':';  
             if ($env{'form.done_'.$key} eq '_done_proctor') {  
                 $seconds .= '_proctor';  
             }              }
         } else {  
             $seconds .= $env{'form.done_'.$key};  
         }  
         if (($env{'form.done_'.$key} eq '_done_proctor') &&  
                 ($env{'form.done_'.$key.'_proctorkey'})) {  
             $seconds .= '_'.$env{'form.done_'.$key.'_proctorkey'};  
         }          }
     }      }
     return if (!$numnotnull);      return if (!$numnotnull);
Line 4014  sub default_selector { Line 3474  sub default_selector {
     return '<input type="text" name="set_'.$thiskey.'" value="'.$showval.'"'.$disabled.' />';      return '<input type="text" name="set_'.$thiskey.'" value="'.$showval.'"'.$disabled.' />';
 }  }
   
 sub string_ip_selector {  
     my ($thiskey, $showval, $readonly) = @_;  
     my %access = (  
                    allow => [],  
                    deny  => [],  
                  );  
     if ($showval ne '') {  
         my @current;  
         if ($showval =~ /,/) {  
             @current = split(/,/,$showval);  
         } else {  
             @current = ($showval);  
         }  
         foreach my $item (@current) {  
             if ($item =~ /^\!([\[\]a-zA-Z\.\d\*\-]+)$/) {  
                 push(@{$access{'deny'}},$1);  
             } elsif ($item =~ /^([\[\]a-zA-Z\.\d\*\-]+)$/) {  
                 push(@{$access{'allow'}},$item);  
             }  
         }  
     }  
     if (!@{$access{'allow'}}) {  
         @{$access{'allow'}} = ('');  
     }  
     if (!@{$access{'deny'}}) {  
         @{$access{'deny'}} = ('');  
     }  
     my ($disabled,$addmore);  
     if ($readonly) {  
         $disabled=' disabled="disabled"';  
     } else {  
         $addmore = "\n".'<button class="LC_add_ipacc_button">'.&mt('Add more').'</button>';  
     }  
     my $output = '<input type="hidden" name="set_'.$thiskey.'" />  
 <table><tr><th>'.&mt('Allow from').'</th><th>'.&mt('Deny from').'</th></tr><tr>';  
     foreach my $acctype ('allow','deny') {  
         $output .= '  
 <td valign="top">  
 <div class="LC_string_ipacc_wrap" id="LC_string_ipacc_'.$acctype.'_'.$thiskey.'">  
   <div class="LC_string_ipacc_inner">'."\n";  
         my $num = 0;  
         foreach my $curr (@{$access{$acctype}}) {  
             $output .= '<div><input type="text" name="setip'.$acctype.'_'.$thiskey.'" value="'.$curr.'"'.$disabled.' />';  
             if ($num > 0) {  
                 $output .= '<a href="#" class="LC_remove_ipacc">'.&mt('Remove').'</a>';  
             }  
             $output .= '</div>'."\n";  
             $num ++;  
         }  
         $output .= '  
   </div>'.$addmore.'  
 </div>  
 </td>';  
    }  
    $output .= '  
 </tr>  
 </table>'."\n";  
     return $output;  
 }  
   
 sub string_deeplink_selector {  
     my ($thiskey, $showval, $readonly) = @_;  
     my (@tables,%values,@current,%titles,%options,%optiontext,%defaults,  
         %selectnull,%domlti,%crslti,@possmenus,%components);  
     @tables = ('upper','lower');  
     %components = (  
                     upper => ['state','others','listing','scope'],  
                     lower => ['protect','menus','target','exit'],  
                   );  
     %titles = &Apache::lonlocal::texthash (  
                   state   => 'Access status',  
                   others  => 'Hide other resources',  
                   listing => 'In Contents and/or Gradebook',  
                   scope   => 'Access scope for link',  
                   protect => 'Link protection',  
                   menus   => 'Menu Items Displayed',  
                   target  => 'Embedded?',  
                   exit    => 'Exit Tool Button?',  
               );  
     %options = (  
                    state   => ['only','off','both'],  
                    others  => ['hide','unhide'],  
                    listing => ['full','absent','grades','details','datestatus'],  
                    scope   => ['res','map','rec'],  
                    protect => ['none','key','ltid','ltic'],  
                    menus   => ['std','colls'],  
                    target  => ['_self','_top'],  
                    exit    => ['no','yes','url'],  
                );  
     %optiontext = &Apache::lonlocal::texthash (  
                     only       => 'deep only',  
                     off        => 'deeplink off',  
                     both       => 'regular + deep',  
                     hide       => 'Hidden',  
                     unhide     => 'Unhidden',  
                     full       => 'Listed (linked) in both',  
                     absent     => 'Not listed',  
                     grades     => 'Listed in grades only',  
                     details    => 'Listed (unlinked) in both',  
                     datestatus => 'Listed (unlinked) inc. status in both',  
                     res        => 'resource only',  
                     map        => 'enclosing map/folder',  
                     rec        => 'recursive map/folder',  
                     none       => 'not in use',  
                     key        => 'key access',  
                     ltic       => 'LTI access (course)',  
                     ltid       => 'LTI access (domain)' ,  
                     std        => 'Standard (all menus)',  
                     colls      => 'Numbered collection',  
                     _self      => 'Embedded',  
                     _top       => 'Not embedded',  
                     no         => 'Not in use',  
                     yes        => 'In use, no URL redirect',  
                     url        => 'In use, redirect to URL',  
                   );  
     %selectnull = &Apache::lonlocal::texthash (  
                     ltic => 'Select Launcher',  
                     ltid => 'Select Launcher',  
                     colls => 'Select',  
                   );  
     if ($showval =~ /,/) {  
         %values=();  
         @current = split(/,/,$showval);  
         ($values{'state'}) = ($current[0] =~ /^(only|off|both)$/);  
         ($values{'others'}) = ($current[1] =~ /^(hide|unhide)$/);  
         ($values{'listing'}) = ($current[2] =~ /^(full|absent|grades|details|datestatus)$/);  
         ($values{'scope'}) = ($current[3] =~ /^(res|map|rec)$/);  
         ($values{'protect'}) = ($current[4] =~ /^(key:[a-zA-Z\d_.!\@#\$%^&*()+=-]+|ltic:\d+|ltid:\d+)$/);  
         ($values{'menus'}) = ($current[5] =~ /^(\d+)$/);  
         ($values{'target'}) = ($current[6] =~ /^(_self|_top)$/);  
         ($values{'exit'}) = ($current[7] =~ /^((?:(?:yes|url)(?:|\:[^:;"',]+))|no)$/);  
     } else {  
         $defaults{'state'} = 'off',  
         $defaults{'others'} = 'unhide',  
         $defaults{'listing'} = 'full';  
         $defaults{'scope'} = 'res';  
         $defaults{'protect'} = 'none';  
         $defaults{'menus'} = '0';  
         $defaults{'target'} = '_top';  
         $defaults{'exit'} = 'yes';  
     }  
     my $disabled;  
     if ($readonly) {  
         $disabled=' disabled="disabled"';  
     }  
     my %courselti =  
         &Apache::lonnet::get_course_lti($env{'course.'.$env{'request.course.id'}.'.num'},  
                                         $env{'course.'.$env{'request.course.id'}.'.domain'});  
     foreach my $item (keys(%courselti)) {  
         if (ref($courselti{$item}) eq 'HASH') {  
             $crslti{$item} = $courselti{$item}{'name'};  
         }  
     }  
     my %lti =  
         &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},  
                                         'linkprot');  
     foreach my $item (keys(%lti)) {  
         if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) {  
             $domlti{$item} = $lti{$item}{'name'};  
         }  
     }  
     if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {  
         foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {  
             my ($num,$value) = split(/\%/,$item);  
             if ($num =~ /^\d+$/) {  
                 push(@possmenus,$num);  
             }  
         }  
     }  
   
     my $output = '<input type="hidden" name="set_'.$thiskey.'" />';  
     foreach my $table ('upper','lower') {  
         next unless (ref($components{$table}) eq 'ARRAY');  
         $output .= '<table width="100%"><tr>';  
         foreach my $item (@{$components{$table}}) {  
             $output .= '<th>'.$titles{$item}.'</th>';  
         }  
         $output .= '</tr><tr>';  
         foreach my $item (@{$components{$table}}) {  
             $output .= '<td>';  
             if (($item eq 'protect') || ($item eq 'menus') || ($item eq 'exit')) {  
                 my $selected = $values{$item};  
                 foreach my $option (@{$options{$item}}) {  
                     if ($item eq 'protect') {  
                         if ($option eq 'ltid') {  
                             next unless (keys(%domlti));  
                         } elsif ($option eq 'ltic') {  
                             next unless (keys(%crslti));  
                         }  
                     } elsif (($item eq 'menus') && ($option eq 'colls')) {  
                         next unless (@possmenus);  
                     }  
                     my $checked;  
                     if ($item eq 'menus') {  
                         if (($selected =~ /^\d+$/) && (@possmenus) &&  
                             (grep(/^\Q$selected\E$/,@possmenus))) {  
                             if ($option eq 'colls') {  
                                 $checked = ' checked="checked"';  
                             }  
                         } elsif (($option eq 'std') && ($selected == 0) && ($selected ne '')) {  
                             $checked = ' checked="checked"';  
                         }  
                     } elsif ($selected =~ /^\Q$option\E/) {  
                         $checked = ' checked="checked"';  
                     }  
                     my $onclick;  
                     unless ($readonly) {  
                         my $esc_key = &js_escape($thiskey);  
                         $onclick = ' onclick="toggleDeepLink(this.form,'."'$item','$esc_key'".');"';  
                     }  
                     $output .= '<span class="LC_nobreak"><label>'.  
                                '<input type="radio" name="deeplink_'.$item.'_'.$thiskey.'" value="'.$option.'"'.$onclick.$disabled.$checked.' />'."\n".  
                                $optiontext{$option}.'</label>';  
                     if (($item eq 'protect') && ($option eq 'key')) {  
                         my $visibility="hidden";  
                         my $currkey;  
                         if ($checked) {  
                             $visibility = "text";  
                             $currkey = (split(/\:/,$values{$item}))[1];  
                         }  
                         $output .= '&nbsp;'.  
                                    '<input type="'.$visibility.'" name="deeplink_'.$option.'_'.$thiskey.'" id="deeplink_'.$option.'_'.$item.'_'.$thiskey.'" value="'.$currkey.'" size="10"'.$disabled.' />';  
                     } elsif (($option eq 'ltic') || ($option eq 'ltid') || ($option eq 'colls')) {  
                         my $display="none";  
                         my ($current,$blankcheck,@possibles);  
                         if ($checked) {  
                             $display = 'inline-block';  
                             if (($option eq 'ltic') || ($option eq 'ltid'))  {  
                                 $current = (split(/\:/,$selected))[1];  
                             } else {  
                                 $current = $selected;  
                             }  
                         } else {  
                             $blankcheck = ' selected="selected"';  
                         }  
                         if ($option eq 'ltid') {  
                             @possibles = keys(%domlti);  
                         } elsif ($option eq 'ltic') {  
                             @possibles = keys(%crslti);  
                         } else {  
                             @possibles = @possmenus;  
                         }  
                         $output .= '<div id="deeplinkdiv_'.$option.'_'.$item.'_'.$thiskey.'"'.  
                                    ' style="display: '.$display.'">&nbsp;<select name="'.  
                                    'deeplink_'.$option.'_'.$thiskey.'"'.$disabled.'>';  
                         if (@possibles > 1) {  
                             $output .= '<option value=""'.$blankcheck.'>'.$selectnull{$option}.  
                                        '</option>'."\n";  
                         }  
                         foreach my $poss (sort { $a <=> $b } @possibles) {  
                             my $selected;  
                             if (($poss == $current) || (scalar(@possibles) ==1)) {  
                                 $selected = ' selected="selected"';  
                             }  
                             my $shown = $poss;  
                             if ($option eq 'ltid') {  
                                 $shown = $domlti{$poss};  
                             } elsif ($option eq 'ltic') {  
                                 $shown = $crslti{$poss};  
                             }  
                             $output .= '<option value="'.$poss.'"'.$selected.'>'.$shown.'</option>';  
                         }  
                         $output .= '</select></div>';  
                     }  
                     $output .= '</span> ';  
                 }  
                 if ($item eq 'exit') {  
                     my $exitsty = 'none';  
                     my $displayval;  
                     if ($values{$item} =~ /^(yes|url)/) {  
                         $exitsty = 'inline-block';  
                         my $currval = (split(/\:/,$values{$item}))[1];  
                         if ($currval eq '') {  
                             $displayval = 'Exit Tool';  
                         } else {  
                             $displayval = $currval;  
                         }  
                     }  
                     $output .= '<div id="deeplinkdiv_'.$item.'_'.$thiskey.'"'.  
                                ' style="display: '.$exitsty.'"><br />'.&mt('Button text').': '.  
                                '<input type="text" name="deeplink_exittext_'.$thiskey.'"'.  
                                ' id="deeplink_exittext_'.$thiskey.'" value="'.$displayval.'"'.  
                                ' size="10"'.$disabled.' /></div>';  
                 }  
             } else {  
                 my $selected = $values{$item};  
                 my $defsel;  
                 if ($selected eq '') {  
                     $defsel = ' selected="selected"';  
                 }  
                 $output .= '<select name="deeplink_'.$item.'_'.$thiskey.'"'.$disabled.'>'."\n".  
                            '<option value=""'.$defsel.'>'.&mt('Please select').'</option>'."\n";  
                 foreach my $option (@{$options{$item}}) {  
                     $output .= '<option value="'.$option.'"';  
                     if ($option eq $selected) {  
                         $output .= ' selected="selected"';  
                     }  
                     $output .= '>'.$optiontext{$option}.'</option>';  
                 }  
                 $output .= '</select>';  
             }  
             $output .= '</td>';  
         }  
         $output .= '</tr></table>'."\n";  
         if ($table eq 'upper') {  
             $output .= '<br />';  
         }  
     }  
     return $output;  
 }  
   
 {  
   
 my %strings =  my %strings =
     (      (
      'string_yesno'       'string_yesno'
Line 4354  my %strings = Line 3501  my %strings =
              => [['yes','Yes'],               => [['yes','Yes'],
                  ['notended','Yes, unless discussion ended'],                   ['notended','Yes, unless discussion ended'],
                  ['no','No']],                   ['no','No']],
      'string_ip'  
              => [['_allowfrom_','Hostname(s), or IP(s) from which access is allowed'],  
                  ['_denyfrom_','Hostname(s) or IP(s) from which access is disallowed']],  
      'string_deeplink'  
              => [['on','Set choices for link protection, resource listing, access scope, shown menu items, embedding, and exit link']],  
      );       );
   
 my %stringmatches = (  
          'string_ip'  
               => [['_allowfrom_','[^\!]+'],  
                   ['_denyfrom_','\!']],  
          'string_deeplink'  
               => [['on','^(only|off|both)\,(hide|unhide)\,(full|absent|grades|details|datestatus)\,(res|map|rec)\,(none|key\:\w+|ltic\:\d+|ltid\:\d+)\,(\d+|)\,_(self|top),(yes|url|no)(|:[^:;\'",]+)$']],  
     );  
   
 my %stringtypes = (  
                     type         => 'string_questiontype',  
                     lenient      => 'string_lenient',  
                     retrypartial => 'string_yesno',  
                     discussvote  => 'string_discussvote',  
                     examcode     => 'string_examcode',  
                     acc          => 'string_ip',  
                     deeplink     => 'string_deeplink',  
                   );  
   
 sub standard_string_options {  sub standard_string_options {
     my ($string_type) = @_;      my ($string_type) = @_;
     if (ref($strings{$string_type}) eq 'ARRAY') {      if (ref($strings{$string_type}) eq 'ARRAY') {
Line 4387  sub standard_string_options { Line 3511  sub standard_string_options {
     return;      return;
 }  }
   
 sub standard_string_matches {  
     my ($string_type) = @_;  
     if (ref($stringmatches{$string_type}) eq 'ARRAY') {  
         return $stringmatches{$string_type};  
     }  
     return;  
 }  
   
 sub string_selector {  sub string_selector {
     my ($thistype, $thiskey, $showval, $name, $readonly) = @_;      my ($thistype, $thiskey, $showval, $name, $readonly) = @_;
   
Line 4425  sub string_selector { Line 3541  sub string_selector {
             }              }
         }          }
     }      }
   
     if ($thistype eq 'string_ip') {  
         return &string_ip_selector($thiskey,$showval,$readonly);  
     } elsif ($thistype eq 'string_deeplink') {  
         return &string_deeplink_selector($thiskey,$showval,$readonly);  
     }  
     
     my ($result,$disabled);      my ($result,$disabled);
   
Line 4485  sub string_selector { Line 3595  sub string_selector {
     return $result;      return $result;
 }  }
   
 sub oldversion_warning {  
     my ($name,$value,$chostname,$cmajor,$cminor,$needsrelease) = @_;  
     my $desc;  
     my %stringtypes = (  
                         type         => 'string_questiontype',  
                         lenient      => 'string_lenient',  
                         retrypartial => 'string_yesno',  
                         discussvote  => 'string_discussvote',  
                         examcode     => 'string_examcode',  
                       );  
     if (exists($stringtypes{$name})) {  
         if ($name eq 'examcode') {  
             $desc = $value;  
         } elsif (ref($strings{$stringtypes{$name}}) eq 'ARRAY') {  
             foreach my $possibilities (@{ $strings{$stringtypes{$name}} }) {  
                 next unless (ref($possibilities) eq 'ARRAY');  
                 my ($parmval, $description) = @{ $possibilities };  
                 if ($parmval eq $value) {  
                     $desc = $description;  
                     last;  
                 }  
             }  
         }  
     } elsif (($name eq 'printstartdate') || ($name eq 'printenddate')) {  
         my $now = time;  
         if ($value =~ /^\d+$/) {  
             if ($name eq 'printstartdate') {  
                 if ($value > $now) {  
                     $desc = &Apache::lonlocal::locallocaltime($value);  
                 }  
             } elsif ($name eq 'printenddate') {  
                 if ($value < $now) {  
                     $desc = &Apache::lonlocal::locallocaltime($value);  
                 }  
             }  
         }  
     }  
     my $standard_name = &standard_parameter_names($name);  
     return '<p class="LC_warning">'.  
            &mt('[_1] was [_2]not[_3] set to [_4].',  
                $standard_name,'<b>','</b>','"'.$desc.'"').'<br />'.  
            &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',  
            $cmajor.'.'.$cminor,$chostname,  
            $needsrelease).  
            '</p>';  
 }  
   
 }  
   
 #  #
 # Shift all start and end dates by $shift  # Shift all start and end dates by $shift
 #  #
Line 4607  sub newoverview { Line 3668  sub newoverview {
 '.  '.
             &Apache::lonhtmlcommon::resize_scrollbox_js('params')."\n".              &Apache::lonhtmlcommon::resize_scrollbox_js('params')."\n".
             &showhide_js()."\n".              &showhide_js()."\n".
             &validateparms_js()."\n".  
             &ipacc_boxes_js()."\n".  
             &done_proctor_js()."\n".  
             &deeplink_js()."\n".  
 '// ]]>  '// ]]>
 </script>  </script>
 ';  ';
Line 4619  sub newoverview { Line 3676  sub newoverview {
     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');      my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
     $r->print($start_page.$breadcrumbs);      $r->print($start_page.$breadcrumbs);
     $r->print(<<ENDOVER);      $r->print(<<ENDOVER);
 <form method="post" action="/adm/parmset?action=newoverview" name="parmform" onsubmit="return validateParms();">  <form method="post" action="/adm/parmset?action=newoverview" name="parmform">
 ENDOVER  ENDOVER
     my @ids=();      my @ids=();
     my %typep=();      my %typep=();
Line 4798  sub overview { Line 3855  sub overview {
     my ($r,$parm_permission) = @_;      my ($r,$parm_permission) = @_;
     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};      my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};      my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};  
     my $js = '<script type="text/javascript">'."\n".  
              '// <![CDATA['."\n".  
              &done_proctor_js()."\n".  
              &validateparms_js()."\n".  
              &ipacc_boxes_js()."\n".  
              &deeplink_js()."\n".  
              '// ]]>'."\n".  
              '</script>'."\n";  
     my $readonly = 1;      my $readonly = 1;
     if ($parm_permission->{'edit'}) {      if ($parm_permission->{'edit'}) {
         undef($readonly);          undef($readonly);
     }      }
     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',      &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
     text=>"Overview Mode"});      text=>"Overview Mode"});
     my $start_page=&Apache::loncommon::start_page('Modify Parameters',$js);      my $start_page=&Apache::loncommon::start_page('Modify Parameters');
     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');      my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
     $r->print($start_page.$breadcrumbs);      $r->print($start_page.$breadcrumbs);
     $r->print('<form method="post" action="/adm/parmset?action=setoverview" name="parmform" onsubmit="return validateParms();">');      $r->print('<form method="post" action="/adm/parmset?action=setoverview" name="parmform">');
   
 # Store modified  # Store modified
     unless ($readonly) {      unless ($readonly) {
Line 6111  sub parameter_releasecheck { Line 5159  sub parameter_releasecheck {
     return $needsnewer;      return $needsnewer;
 }  }
   
   sub oldversion_warning {
       my ($name,$value,$chostname,$cmajor,$cminor,$needsrelease) = @_;
       my $desc;
       my %stringtypes = (
                           type         => 'string_questiontype',
                           lenient      => 'string_lenient',
                           retrypartial => 'string_yesno',
                           discussvote  => 'string_discussvote',
                           examcode     => 'string_examcode',
                         );
       if (exists($stringtypes{$name})) {
           if ($name eq 'examcode') {
               $desc = $value;
           } elsif (ref($strings{$stringtypes{$name}}) eq 'ARRAY') {
               foreach my $possibilities (@{ $strings{$stringtypes{$name}} }) {
                   next unless (ref($possibilities) eq 'ARRAY');
                   my ($parmval, $description) = @{ $possibilities };
                   if ($parmval eq $value) {
                       $desc = $description;
                       last;
                   }
               }
           }
       } elsif (($name eq 'printstartdate') || ($name eq 'printenddate')) {
           my $now = time;
           if ($value =~ /^\d+$/) {
               if ($name eq 'printstartdate') {
                   if ($value > $now) {
                       $desc = &Apache::lonlocal::locallocaltime($value);
                   }
               } elsif ($name eq 'printenddate') {
                   if ($value < $now) {
                       $desc = &Apache::lonlocal::locallocaltime($value);
                   }
               }
           }
       }
       my $standard_name = &standard_parameter_names($name);
       return '<p class="LC_warning">'.
              &mt('[_1] was [_2]not[_3] set to [_4].',
                  $standard_name,'<b>','</b>','"'.$desc.'"').'<br />'.
              &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
              $cmajor.'.'.$cminor,$chostname,
              $needsrelease).
              '</p>';
   }
   
 sub get_permission {  sub get_permission {
     my %permission;      my %permission;
     my $allowed = 0;      my $allowed = 0;

Removed from v.1.522.2.28.4.8  
changed lines
  Added in v.1.522.2.31


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