[LON-CAPA-cvs] cvs: loncom /interface courseprefs.pm domainprefs.pm lonconfigsettings.pm

raeburn raeburn at source.lon-capa.org
Mon Feb 14 23:28:01 EST 2022


raeburn		Tue Feb 15 04:28:01 2022 EDT

  Modified files:              
    /loncom/interface	domainprefs.pm lonconfigsettings.pm 
                     	courseprefs.pm 
  Log:
  - Bug 6907
    Link Protectors for deep-linking from launch from LTI Consumer can be
    configured at both a domain level and a course level.
  
  
-------------- next part --------------
Index: loncom/interface/domainprefs.pm
diff -u loncom/interface/domainprefs.pm:1.405 loncom/interface/domainprefs.pm:1.406
--- loncom/interface/domainprefs.pm:1.405	Mon Feb 14 02:48:46 2022
+++ loncom/interface/domainprefs.pm	Tue Feb 15 04:28:01 2022
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Handler to set domain-wide configuration settings
 #
-# $Id: domainprefs.pm,v 1.405 2022/02/14 02:48:46 raeburn Exp $
+# $Id: domainprefs.pm,v 1.406 2022/02/15 04:28:01 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -249,13 +249,16 @@
         }
     }
     if (ref($domconfig{'ltisec'}) eq 'HASH') {
-        if (ref($domconfig{'ltisec'}{'prot'}) eq 'HASH') {
+        if (ref($domconfig{'ltisec'}{'linkprot'}) eq 'HASH') {
             if (ref($encconfig{'linkprot'}) eq 'HASH') {
-                foreach my $id (keys(%{$domconfig{'ltisec'}{'prot'}})) {
-                    if ((ref($domconfig{'ltisec'}{'prot'}{$id}) eq 'HASH') &&
+                foreach my $id (keys(%{$domconfig{'ltisec'}{'linkprot'}})) {
+                    unless ($id =~ /^\d+$/) {
+                        delete($domconfig{'ltisec'}{'linkprot'}{$id});
+                    }
+                    if ((ref($domconfig{'ltisec'}{'linkprot'}{$id}) eq 'HASH') &&
                         (ref($encconfig{'linkprot'}{$id}) eq 'HASH')) {
                         foreach my $item ('key','secret') {
-                            $domconfig{'ltisec'}{'prot'}{$id}{$item} = $encconfig{'linkprot'}{$id}{$item};
+                            $domconfig{'ltisec'}{'linkprot'}{$id}{$item} = $encconfig{'linkprot'}{$id}{$item};
                         }
                     }
                 }
@@ -637,7 +640,7 @@
                               col2 => 'Settings'},
                              {col1 => 'Rules for shared secrets', 
                               col2 => 'Settings'},
-                             {col1 => 'Link Protectors (domain)',
+                             {col1 => 'Link Protectors',
                               col2 => 'Settings'},
                              {col1 => 'Consumers',
                               col2 => 'Settings'},],
@@ -3429,6 +3432,7 @@
         push(@jsarray,$ordered{$item});
     }
     my $jstext = '    var lti = Array('."'".join("','", at jsarray)."'".');'."\n";
+    my $linkprot_js = &Apache::courseprefs::linkprot_javascript();
     return <<"ENDSCRIPT";
 <script type="text/javascript">
 // <![CDATA[
@@ -3473,6 +3477,9 @@
     }
     return;
 }
+
+$linkprot_js
+
 // ]]>
 </script>
 
@@ -6490,6 +6497,9 @@
             if (exists($settings->{'linkprot'})) {
                 if (ref($settings->{'linkprot'}) eq 'HASH') {
                     %linkprot = %{$settings->{'linkprot'}};
+                    if ($linkprot{'lock'}) {
+                        delete($linkprot{'lock'});
+                    }
                 }
             }
         } else {
@@ -6595,8 +6605,9 @@
         $$rowtotal += $itemcount;
     } elsif ($position eq 'middle') {
         $datatable = &password_rules('secrets',\$itemcount,\%rules);
+        $$rowtotal += $itemcount;
     } elsif ($position eq 'lower') {
-        $datatable .= '<tr><td>Not set yet</td><td>To be done</td></tr>';
+         $datatable .= &Apache::courseprefs::print_linkprotection($dom,'',$settings,$rowtotal,'','','domain');
     } else {
         my $maxnum = 0;
         my %ordered;
@@ -15828,12 +15839,20 @@
 
     my %menutitles = &ltimenu_titles();
 
-    my (%currltisec,%secchanges,%newltisec,%keyset,%newkeyset);
+    my (%currltisec,%secchanges,%newltisec,%newltienc,%keyset,%newkeyset);
     $newltisec{'private'}{'keys'} = [];
     $newltisec{'encrypt'} = {};
     $newltisec{'rules'} = {};
+    $newltisec{'linkprot'} = {};
     if (ref($domconfig{'ltisec'}) eq 'HASH') {
         %currltisec = %{$domconfig{'ltisec'}};
+        if (ref($currltisec{'linkprot'}) eq 'HASH') {
+            foreach my $id (keys(%{$currltisec{'linkprot'}})) {
+                unless ($id =~ /^\d+$/) {
+                    delete($currltisec{'linkprot'}{$id});
+                }
+            }
+        }
         if (ref($currltisec{'private'}) eq 'HASH') {
             if (ref($currltisec{'private'}{'keys'}) eq 'ARRAY') {
                 $newltisec{'private'}{'keys'} = $currltisec{'private'}{'keys'};
@@ -15895,6 +15914,62 @@
         }
     }
 
+    my (%linkprotchg,$linkprotoutput,$is_home);
+    my $proterror = &Apache::courseprefs::process_linkprot($dom,'',$currltisec{'linkprot'},
+                                                           \%linkprotchg,'domain');
+    my $home = &Apache::lonnet::domain($dom,'primary');
+    unless (($home eq 'no_host') || ($home eq '')) {
+        my @ids=&Apache::lonnet::current_machine_ids();
+        foreach my $id (@ids) { if ($id eq $home) { $is_home=1; } }
+    }
+
+    if (keys(%linkprotchg)) {
+        $secchanges{'linkprot'} = 1;
+        my %oldlinkprot;
+        if (ref($currltisec{'linkprot'}) eq 'HASH') {
+            %oldlinkprot = %{$currltisec{'linkprot'}};
+        }
+        foreach my $id (keys(%linkprotchg)) {
+            if (ref($linkprotchg{$id}) eq 'HASH') {
+                foreach my $inner (keys(%{$linkprotchg{$id}})) {
+                    if (($inner eq 'secret') || ($inner eq 'key')) {
+                        if ($is_home) {
+                            $newltienc{$id}{$inner} = $linkprotchg{$id}{$inner};
+                        }
+                    }
+                }
+            } else {
+                $newltisec{'linkprot'}{$id} = $linkprotchg{$id};
+            }
+        }
+        $linkprotoutput = &Apache::courseprefs::store_linkprot($dom,'','domain',\%linkprotchg,\%oldlinkprot);
+        if (keys(%linkprotchg)) {
+            %{$newltisec{'linkprot'}} = %linkprotchg;
+        }
+    }
+    if (ref($currltisec{'linkprot'}) eq 'HASH') {
+        foreach my $id (%{$currltisec{'linkprot'}}) {
+            next if ($id !~ /^\d+$/);
+            unless (exists($linkprotchg{$id})) {
+                if (ref($currltisec{'linkprot'}{$id}) eq 'HASH') {
+                    foreach my $inner (keys(%{$currltisec{'linkprot'}{$id}})) {
+                        if (($inner eq 'secret') || ($inner eq 'key')) {
+                            if ($is_home) {
+                                $newltienc{$id}{$inner} = $currltisec{'linkprot'}{$id}{$inner};
+                            }
+                        } else {
+                            $newltisec{'linkprot'}{$id}{$inner} = $currltisec{'linkprot'}{$id}{$inner};
+                        }
+                    }
+                } else {
+                    $newltisec{'linkprot'}{$id} = $currltisec{'linkprot'}{$id};
+                }
+            }
+        }
+    }
+    if ($proterror) {
+        $errors .= '<li>'.$proterror.'</li>';
+    }
     my (@items,%deletions,%itemids);
     if ($env{'form.lti_add'}) {
         my $consumer = $env{'form.lti_consumer_add'};
@@ -16200,8 +16275,16 @@
     my %ltihash = (
                       $action => { %confhash }
                   );
+    my %ltienchash = (
+                         $action => { %encconfig }
+                     );
     if (keys(%secchanges)) {
         $ltihash{'ltisec'} = \%newltisec;
+        if ($secchanges{'linkprot'}) {
+            if ($is_home) {
+                $ltienchash{'linkprot'} = \%newltienc;
+            }
+        }
     }
     my $putresult = &Apache::lonnet::put_dom('configuration',\%ltihash,$dom);
     if ($putresult eq 'ok') {
@@ -16219,9 +16302,6 @@
                 }
             }
         }
-        my %ltienchash = (
-                             $action => { %encconfig }
-                         );
         &Apache::lonnet::put_dom('encconfig',\%ltienchash,$dom,undef,1);
         if ((keys(%changes) == 0) && (keys(%secchanges) == 0)) {
             return &mt('No changes made.');
@@ -16298,6 +16378,8 @@
                             }
                         }
                     }
+                } elsif ($item eq 'linkprot') {
+                    $resulttext .= $linkprotoutput;
                 }
             }
         }
Index: loncom/interface/lonconfigsettings.pm
diff -u loncom/interface/lonconfigsettings.pm:1.58 loncom/interface/lonconfigsettings.pm:1.59
--- loncom/interface/lonconfigsettings.pm:1.58	Mon Feb 14 02:48:46 2022
+++ loncom/interface/lonconfigsettings.pm	Tue Feb 15 04:28:01 2022
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Handler to set domain-wide configuration settings
 #
-# $Id: lonconfigsettings.pm,v 1.58 2022/02/14 02:48:46 raeburn Exp $
+# $Id: lonconfigsettings.pm,v 1.59 2022/02/15 04:28:01 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -40,9 +40,9 @@
 use LONCAPA qw(:DEFAULT :match); 
 
 sub print_header {
-    my ($r,$phase,$context,$jscript,$container,$instcode,$dom,$values) = @_;
+    my ($r,$phase,$context,$jscript,$container,$instcode,$dom,$confname,$values) = @_;
     my ($pagetitle,$brcrumtitle,$action,$call_category_check,$instcode_check,
-        $crstype, at actions, at code_order);
+        $linkprot_check,$crstype, at actions, at code_order);
     if ($phase eq 'display') {
         @actions = &Apache::loncommon::get_env_multiple('form.actions');
     }
@@ -116,6 +116,85 @@
 ENDSCRIPT
                 }
             }
+            if (($context eq 'course') && ($phase eq 'display') &&
+                (grep(/^linkprotection$/, at actions))) {
+                my $allowed;
+                my $home = &Apache::lonnet::homeserver($confname,$dom);
+                unless ($home eq 'no_host') {
+                    my @ids=&Apache::lonnet::current_machine_ids();
+                    foreach my $id (@ids) { if ($id eq $home) { $allowed=1; } }
+                }
+                if ($allowed) {
+                    my (@changeable, at settable);
+                    if (ref($values->{'linkprotection'}) eq 'HASH') {
+                        if (keys(%{$values->{'linkprotection'}})) {
+                            my @current = sort { $a <=> $b } keys(%{$values->{'linkprotection'}});
+                            if (@current) {
+                                for (my $i=0; $i<@current; $i++) {
+                                    my $num = $current[$i];
+                                    if (ref($values->{'linkprotection'}->{$num}) eq 'HASH') {
+                                        if ($values->{'linkprotection'}->{$num}->{'usable'}) {
+                                            push(@changeable,$i);
+                                        } else {
+                                            push(@settable,$i);
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    my ($numrules,$intargjs);
+$linkprot_check .= <<ENDJS;
+
+var linkprotradio = '';
+var secretinput = ''; 
+ENDJS
+                    if (@changeable) {
+                        foreach my $num (@changeable) {
+                            ($numrules,$intargjs) =
+                                &Apache::loncommon::passwd_validation_js('secretinput',$dom,'linkprot',$num);
+                            if ($numrules) {
+                                $linkprot_check .= <<ENDJS;
+
+linkprotradio = document.display.elements['linkprot_changesecret_$num'];
+secretinput = document.display.elements['linkprot_secret_$num'].value;
+if (linkprotradio.length) {
+    for (var i=0; i<linkprotradio.length; i++) {
+        if (linkprotradio[i].checked) {
+            if (linkprotradio[i].value == 1) {
+                $intargjs
+            }
+        }
+    }
+}
+ENDJS
+                            }
+                        }
+                    }
+                    if (@settable) {
+                        foreach my $num (@changeable) {
+                            ($numrules,$intargjs) =
+                                &Apache::loncommon::passwd_validation_js('secretinput',$dom,'linkprot',$num);
+                            if ($numrules) {
+                                $linkprot_check .= <<ENDJS;
+secretinput = document.display.elements['linkprot_secret_$num'].value;
+$intargjs
+ENDJS
+                            }
+                        }
+                    }
+                    ($numrules,$intargjs) =
+                        &Apache::loncommon::passwd_validation_js('secretinput',$dom,'linkprot','add');
+                    if ($numrules) {
+                        $linkprot_check .= <<ENDJS
+secretinput = document.display.elements['linkprot_secret_add'].value;
+if (document.display.elements['linkprot_add'].checked) {
+    $intargjs      
+}
+ENDJS
+                    }
+                }
+            }
         }
     }
     my $alert = &mt('You must select at least one functionality type to display.');
@@ -146,7 +225,7 @@
             return;
         }
     }
-    '.$instcode_check.$call_category_check.'
+    '.$instcode_check.$call_category_check.$linkprot_check.'
     formname.submit();
 }'."\n";
     if ($phase eq 'pickactions') {
@@ -311,12 +390,12 @@
                             }
                             if (ref($values->{'linkprotection'}->{$i}) eq 'HASH') {
                                 if ($values->{'linkprotection'}->{$i}->{'usable'}) {
-                                    $onload .= "toggleLTI(document.display,'$num','secret');";
+                                    $onload .= "toggleLinkProt(document.display,'$num','secret');";
                                 }
                             }
                             if ($ltiauth) {
-                                $onload .= "toggleLTIReqUser(document.display,'requser','optional','1','block','$num');".
-                                           "toggleLTIReqUser(document.display,'mapuser','userfield','other','inline-block','$num');";
+                                $onload .= "toggleLinkProtReqUser(document.display,'requser','optional','1','block','$num');".
+                                           "toggleLinkProtReqUser(document.display,'mapuser','userfield','other','inline-block','$num');";
                             }
                         }
                     }
@@ -481,7 +560,7 @@
     if (ref($values) eq 'HASH') {
         $instcode = $values->{'internal.coursecode'};
     }
-    &print_header($r,$phase,$context,$jscript,$container,$instcode,$dom,$values);
+    &print_header($r,$phase,$context,$jscript,$container,$instcode,$dom,$confname,$values);
     my $divwidth = 900;
     if ((ref($prefs_order) eq 'ARRAY') && (ref($prefs) eq 'HASH') && (ref($values) eq 'HASH')) { 
         if (@actions > 0) {
@@ -536,7 +615,7 @@
                                     $settings = $values->{'ltisec'};
                                 }
                             } elsif (ref($values->{'lti'}) eq 'HASH') {
-                                $settings = $values->{'lti'};   
+                                $settings = $values->{'lti'};
                             }
                         }
                         ($output{$item},$rowtotal{$item}) =
Index: loncom/interface/courseprefs.pm
diff -u loncom/interface/courseprefs.pm:1.101 loncom/interface/courseprefs.pm:1.102
--- loncom/interface/courseprefs.pm:1.101	Mon Feb  7 06:16:44 2022
+++ loncom/interface/courseprefs.pm	Tue Feb 15 04:28:01 2022
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Handler to set configuration settings for a course
 #
-# $Id: courseprefs.pm,v 1.101 2022/02/07 06:16:44 raeburn Exp $
+# $Id: courseprefs.pm,v 1.102 2022/02/15 04:28:01 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -52,12 +52,16 @@
 
 =item process_changes()
 
+=item process_linkprot()
+
 =item get_sec_str()
 
 =item check_clone()
 
 =item store_changes()
 
+=item store_linkprot()
+
 =item update_env()
 
 =item display_disallowed()
@@ -365,28 +369,28 @@
     }
 
     my %values=&Apache::lonnet::dump('environment',$cdom,$cnum);
-    my %lti=&Apache::lonnet::dump('lti',$cdom,$cnum,undef,undef,undef,1);
+    my %linkprot=&Apache::lonnet::dump('lti',$cdom,$cnum,undef,undef,undef,1);
     my %ltienc = &Apache::lonnet::dump('nohist_ltienc',$cdom,$cnum,undef,undef,undef,1);
-    foreach my $id (keys(%lti)) {
-        if (ref($lti{$id}) eq 'HASH') {
+    foreach my $id (keys(%linkprot)) {
+        if (ref($linkprot{$id}) eq 'HASH') {
             if (ref($ltienc{$id}) eq 'HASH') {
-                $values{'linkprotection'}{$id} = { %{$lti{$id}}, %{$ltienc{$id}} };
+                $values{'linkprot'}{$id} = { %{$linkprot{$id}}, %{$ltienc{$id}} };
             } else {
-                $values{'linkprotection'}{$id} = $lti{$id};
+                $values{'linkprot'}{$id} = $linkprot{$id};
             }
         }
         unless ($phase eq 'process') {
-            if (ref($values{'linkprotection'}{$id}) eq 'HASH') {
-                delete($values{'linkprotection'}{$id}{'secret'});
+            if (ref($values{'linkprot'}{$id}) eq 'HASH') {
+                delete($values{'linkprot'}{$id}{'secret'});
             }
         }
     }
-    if ($lti{'lock'}) {
-        delete($lti{'lock'});
+    if ($linkprot{'lock'}) {
+        delete($linkprot{'lock'});
     }
     my @prefs_order = ('courseinfo','localization','feedback','discussion',
                        'classlists','appearance','grading','printouts',
-                       'menuitems','linkprotection','spreadsheet','bridgetasks',
+                       'menuitems','linkprot','spreadsheet','bridgetasks',
                        'lti','other');
 
     my %prefs = (
@@ -578,7 +582,7 @@
                          menucollections => 'Menu collections',
                                  },
                    },
-        'linkprotection' =>
+        'linkprot' =>
                    {
                      text => 'Link protection',
                      help => 'Course_Prefs_Linkprotection',
@@ -793,8 +797,8 @@
         $output .= &print_lti($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype,$noedit);
     } elsif ($action eq 'menuitems') {
         $output .= &print_menuitems('bottom',$cdom,$settings,$itemtext,\$rowtotal,$crstype,$noedit);
-    } elsif ($action eq 'linkprotection') {
-        $output .= &print_linkprotection($cdom,$cnum,$settings,\$rowtotal,$crstype,$noedit);
+    } elsif ($action eq 'linkprot') {
+        $output .= &print_linkprotection($cdom,$cnum,$settings,\$rowtotal,$crstype,$noedit,'course');
     } elsif ($action eq 'other') {
         $output .= &print_other($cdom,$settings,$allitems,\$rowtotal,$crstype,$noedit);
     }
@@ -808,7 +812,7 @@
 
 sub process_changes {
     my ($cdom,$cnum,$action,$values,$item,$changes,$allitems,$disallowed,$crstype) = @_;
-    my (%newvalues,%lti,%ltienc,$ltiauth,$errors);
+    my (%newvalues,$errors);
     if (ref($item) eq 'HASH') {
         if (ref($changes) eq 'HASH') {
             my @ordered;
@@ -825,14 +829,11 @@
                         }
                     }
                 }
-            } elsif ($action eq 'linkprotection') {
+            } elsif ($action eq 'linkprot') {
                 if (ref($values->{$action}) eq 'HASH') {
                     foreach my $id (keys(%{$values->{$action}})) {
                         if ($id =~ /^\d+$/) {
                             push(@ordered,$id);
-                            unless (ref($values->{$action}->{$id}) eq 'HASH') {
-                                $lti{$id} = '';
-                            }
                         }
                     }
                 }
@@ -840,12 +841,6 @@
                 if (($env{'form.linkprot_add'}) && ($env{'form.linkprot_maxnum'} =~ /^\d+$/)) {
                     push(@ordered,$env{'form.linkprot_maxnum'});
                 }
-                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'};
-                }
             } elsif (ref($item->{'ordered'}) eq 'ARRAY') {
                 if ($action eq 'courseinfo') {
                     my ($can_toggle_cat,$can_categorize) =
@@ -983,145 +978,9 @@
                     } elsif ($values->{'menucollections'}) {
                         $changes->{'menucollections'} = '';
                     }
-                } elsif ($action eq 'linkprotection') {
-                    my %menutitles = &ltimenu_titles();
-                    my $switchserver = &check_switchserver($cdom,$cnum);
-                    my (@items,%deletions,%itemids,%haschanges);
-                    if ($env{'form.linkprot_add'}) {
-                        my $name = $env{'form.linkprot_name_add'};
-                        $name =~ s/(`)/'/g;
-                        my ($newid,$error) = &get_courselti_id($cdom,$cnum,$name);
-                        if ($newid) {
-                            $itemids{'add'} = $newid;
-                            push(@items,'add');
-                            $haschanges{$newid} = 1;
-                        } else {
-                            $errors .= '<span class="LC_error">'.
-                                       &mt('Failed to acquire unique ID for link protection').
-                                       '</span>';
-                        }
-                    }
-                    if (ref($values->{$action}) eq 'HASH') {
-                        my @todelete = &Apache::loncommon::get_env_multiple('form.linkprot_del');
-                        my $maxnum = $env{'form.linkprot_maxnum'};
-                        for (my $i=0; $i<=$maxnum; $i++) {
-                            my $itemid = $env{'form.linkprot_id_'.$i};
-                            $itemid =~ s/\D+//g;
-                            if ($itemid) {
-                                if (ref($values->{$action}->{$itemid}) eq 'HASH') {
-                                    push(@items,$i);
-                                    $itemids{$i} = $itemid;
-                                    if ((@todelete > 0) && (grep(/^$i$/, at todelete))) {
-                                        $deletions{$itemid} = $values->{$action}->{$itemid}->{'name'};
-                                    }
-                                }
-                            }
-                        }
-                    }
-
-                    foreach my $idx (@items) {
-                        my $itemid = $itemids{$idx};
-                        next unless ($itemid);
-                        if (exists($deletions{$itemid})) {
-                            $lti{$itemid} = $deletions{$itemid};
-                            $haschanges{$itemid} = 1;
-                            next;
-                        }
-                        my %current;
-                        if (ref($values->{$action}) eq 'HASH') {
-                            if (ref($values->{$action}->{$itemid}) eq 'HASH') {
-                                foreach my $key (keys(%{$values->{$action}->{$itemid}})) {
-                                    $current{$key} = $values->{$action}->{$itemid}->{$key};
-                                }
-                            }
-                        }
-                        foreach my $inner ('name','lifetime','version') {
-                            my $formitem = 'form.linkprot_'.$inner.'_'.$idx;
-                            $env{$formitem} =~ s/(`)/'/g;
-                            if ($inner eq 'lifetime') {
-                                $env{$formitem} =~ s/[^\d.]//g;
-                            }
-                            unless ($idx eq 'add') {
-                                if ($current{$inner} ne $env{$formitem}) {
-                                    $haschanges{$itemid} = 1;
-                                }
-                            }
-                            if ($env{$formitem} ne '') {
-                                $lti{$itemid}{$inner} = $env{$formitem};
-                            }
-                        }
-                        if ($ltiauth) {
-                            my $reqitem = 'form.linkprot_requser_'.$idx;
-                            $env{$reqitem} =~ s/(`)/'/g;
-                            unless ($idx eq 'add') {
-                                if ($current{'requser'} ne $env{$reqitem}) {
-                                    $haschanges{$itemid} = 1;
-                                }
-                            }
-                            if ($env{$reqitem} ne '') {
-                                $lti{$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 '') {
-                                                $lti{$itemid}{$inner} = $mapuser;
-                                            } else {
-                                                delete($lti{$itemid}{'requser'});
-                                                last;
-                                            }
-                                        } elsif ($env{$formitem} eq 'sourcedid') {
-                                            $lti{$itemid}{$inner} = 'lis_person_sourcedid';
-                                        } elsif ($env{$formitem} eq 'email') {
-                                            $lti{$itemid}{$inner} = 'lis_person_contact_email_primary';
-                                        }
-                                    } else {
-                                        $lti{$itemid}{$inner} = $env{$formitem};
-                                    }
-                                    unless ($idx eq 'add') {
-                                        if ($current{$inner} ne $lti{$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 '') {
-                                $lti{$itemid}{'key'} = $env{$keyitem};
-                            }
-                            my $secretitem = 'form.linkprot_secret_'.$idx;
-                            $env{$secretitem} =~ s/(`)/'/g;
-                            if ($current{'usable'}) {
-                                if ($env{'form.linkprot_changesecret_'.$idx}) {
-                                    if ($env{$secretitem} ne '') {
-                                        $lti{$itemid}{'secret'} = $env{$secretitem};
-                                        $haschanges{$itemid} = 1;
-                                    }
-                                } else {
-                                    $lti{$itemid}{'secret'} = $current{'secret'};
-                                }
-                            } elsif ($env{$secretitem} ne '') {
-                                $lti{$itemid}{'secret'} = $env{$secretitem};
-                                $haschanges{$itemid} = 1;
-                            }
-                        }
-                    }
-                    if (keys(%haschanges)) {
-                        foreach my $entry (keys(%haschanges)) {
-                            $changes->{$entry} = $lti{$entry};
-                        }
+                } elsif ($action eq 'linkprot') {
+                    if (ref($values) eq 'HASH') {
+                        $errors = &process_linkprot($cdom,$cnum,$values->{$action},$changes,'course');
                     }
                 } else {
                     foreach my $entry (@ordered) {
@@ -1616,23 +1475,201 @@
     return $errors;
 }
 
-sub get_courselti_id {
-    my ($cdom,$cnum,$name) = @_;
-    # get lock on lti db in course
+sub process_linkprot {
+    my ($cdom,$cnum,$values,$changes,$context) = @_;
+    my ($dest,$ltiauth,$errors,%linkprot);
+    if (ref($values) eq 'HASH') {
+        foreach my $id (keys(%{$values})) {
+            if ($id =~ /^\d+$/) {
+                unless (ref($values->{$id}) eq 'HASH') {
+                    $linkprot{$id} = '';
+                }
+            }
+        }
+    }
+    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$/, at 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'} ne $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 '') {
+                        $linkprot{$itemid}{'secret'} = $env{$secretitem};
+                        $haschanges{$itemid} = 1;
+                    }
+                } else {
+                    $linkprot{$itemid}{'secret'} = $current{'secret'};
+                }
+            } elsif ($env{$secretitem} ne '') {
+                $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 = &Apache::lonnet::newput('lti',$lockhash,$cdom,$cnum);
+    my $gotlock;
+    if ($context eq 'domain') {
+        $gotlock = &Apache::lonnet::newput_dom('linkprot',$lockhash,$cdom);
+    } else {
+        $gotlock = &Apache::lonnet::newput('lti',$lockhash,$cdom,$cnum);
+    }
     my ($id,$error);
     while (($gotlock ne 'ok') && ($tries<10)) {
         $tries ++;
         sleep (0.1);
-        $gotlock = &Apache::lonnet::newput('lti',$lockhash,$cdom,$cnum);
+        if ($context eq 'domain') {
+            $gotlock = &Apache::lonnet::newput_dom('linkprot',$lockhash,$cdom); 
+        } else {
+            $gotlock = &Apache::lonnet::newput('lti',$lockhash,$cdom,$cnum);
+        }
     }
     if ($gotlock eq 'ok') {
-        my %currids  = &Apache::lonnet::dump('lti',$cdom,$cnum,undef,undef,undef,1);
+        my %currids;
+        if ($context eq 'domain') {
+            %currids = &Apache::lonnet::dump_dom('linkprot',$cdom);
+        } else {
+            %currids  = &Apache::lonnet::dump('lti',$cdom,$cnum,undef,undef,undef,1);
+        }
         if ($currids{'lock'}) {
             delete($currids{'lock'});
             if (keys(%currids)) {
@@ -1646,14 +1683,25 @@
                 $id = 1;
             }
             if ($id) {
-                unless (&Apache::lonnet::newput('lti',{ $id => $name },$cdom,$cnum) eq 'ok') {
-                    $error = 'nostore';
+                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 = &Apache::lonnet::del('lti',['lock'],$cdom,$cnum);
+        my $dellockoutcome; 
+        if ($context eq 'domain') {
+            $dellockoutcome = &Apache::lonnet::del_dom('linkprot',['lock'],$cdom);
+        } else {
+            $dellockoutcome = &Apache::lonnet::del('lti',['lock'],$cdom,$cnum);
+        }
     } else {
         $error = 'nolock';
     }
@@ -1704,10 +1752,10 @@
     my ($chome,$output);
     my (%storehash, at delkeys, at need_env_update, at oldcloner,%oldlinkprot);
     if ((ref($values) eq 'HASH') && (ref($changes) eq 'HASH')) {
-        if (ref($values->{'linkprotection'}) eq 'HASH') {
-            %oldlinkprot = %{$values->{'linkprotection'}};
+        if (ref($values->{'linkprot'}) eq 'HASH') {
+            %oldlinkprot = %{$values->{'linkprot'}};
         }
-        delete($values->{'linkprotection'});
+        delete($values->{'linkprot'});
         %storehash = %{$values};
     } else {
         if ($crstype eq 'Community') {
@@ -1720,7 +1768,7 @@
     my ($numchanges,$skipstore);
     if (ref($changes) eq 'HASH') {
         $numchanges = scalar(keys(%{$changes}));
-        if (($numchanges == 1) && (exists($changes->{'linkprotection'}))) {
+        if (($numchanges == 1) && (exists($changes->{'linkprot'}))) {
             $skipstore = 1;
         } elsif (!$numchanges) {
             if ($crstype eq 'Community') {
@@ -1756,127 +1804,8 @@
                                            "'$storehash{$key}'")).'</li>';
                             }
                         }
-                    } elsif ($item eq 'linkprotection') {
-                        my ($ltiauth,%ltienc,$lti_save_error);
-                        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->{$item}) eq 'HASH') {
-                            foreach my $id (sort { $a <=> $b } keys(%{$changes->{$item}})) {
-                                if (ref($changes->{$item}->{$id}) eq 'HASH') {
-                                    if (exists($changes->{$item}->{$id}->{'key'})) {
-                                        $ltienc{$id}{'key'} = $changes->{$item}->{$id}->{'key'};
-                                        delete($changes->{$item}->{$id}->{'key'});
-                                    }
-                                    if (exists($changes->{$item}->{$id}->{'secret'})) {
-                                        $ltienc{$id}{'secret'} = $changes->{$item}->{$id}->{'secret'};
-                                        delete($changes->{$item}->{$id}->{'secret'});
-                                    } elsif (ref($oldlinkprot{$id}) eq 'HASH') {
-                                        if (exists($oldlinkprot{$id}{'usable'})) {
-                                            $changes->{$item}->{$id}->{'usable'} = 1;
-                                        }
-                                    }
-                                }
-                            }
-                        }
-                        if (keys(%ltienc) > 0) {
-                            if (&Apache::lonnet::put('nohist_ltienc',\%ltienc,$cdom,$cnum,1) eq 'ok') {
-                                foreach my $id (keys(%ltienc)) {
-                                    if (exists($ltienc{$id}{'secret'})) {
-                                        $changes->{$item}->{$id}->{'usable'} = 1;
-                                    }
-                                }
-                            } else {
-                                $lti_save_error = 1;
-                            }
-                        }
-                        unless ($lti_save_error) {
-                            if (&Apache::lonnet::put('lti',$changes->{$item},$cdom,$cnum,1) eq 'ok') {
-                                my $hashid=$cdom.'_'.$cnum;
-                                &Apache::lonnet::devalidate_cache_new('courselti',$hashid);
-                                $chome = &Apache::lonnet::homeserver($cnum,$cdom);
-                                unless (($chome eq 'no_host') || ($chome eq '')) {
-                                    my @ids=&Apache::lonnet::current_machine_ids();
-                                    if (grep(/^\Q$chome\E$/, at ids)) {
-                                        &Apache::lonnet::devalidate_cache_new('courseltienc',$hashid);
-                                    }
-                                }
-                                foreach my $id (sort { $a <=> $b } %{$changes->{$item}}) {
-                                    if (ref($changes->{$item}->{$id}) eq 'HASH') {
-                                        my %values = %{$changes->{$item}->{$id}};
-                                        my %desc = &linkprot_names();
-                                        my $display;
-                                        foreach my $title ('name','lifetime','version','key','secret') {
-                                            if (($title eq 'key') || ($title eq 'secret')) {
-                                                if (ref($ltienc{$id}) eq 'HASH') {
-                                                    if (exists($ltienc{$id}{$title})) {
-                                                        if ($title eq 'secret') {
-                                                            my $length = length($ltienc{$id}{$title});
-                                                            $display .= $desc{$title}.': '.('*' x $length).', ';
-                                                        } else {
-                                                            $display .= $desc{$title}.': '.$ltienc{$id}{$title}.', ';
-                                                        }
-                                                    }
-                                                }
-                                            } elsif ($title eq 'version') {
-                                                if ($values{$title} eq 'LTI-1p0') {
-                                                    $display .= $desc{$title}.': 1.1, ';
-                                                }
-                                            } else {
-                                                $display .= $desc{$title}.': '.$values{$title}.', ';
-                                            }
-                                        }
-                                        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) {
-                            my @deletions;
-                            foreach my $id (sort { $a <=> $b } keys(%{$changes->{$item}})) {
-                                unless (ref($changes->{$item}->{$id}) eq 'HASH') {
-                                    push (@deletions,$id);
-                                }
-                            }
-                            if (@deletions) {
-                                &Apache::lonnet::del('nohist_ltienc',\@deletions,$cdom,$cnum);
-                            }
-                        }
-                        if ($lti_save_error) {
-                            $output .= '<li>'.
-                                       '<span class="LC_error">'.
-                                       &mt('An error occurred when saving changes to link protection settings, which remain unchanged.').
-                                       '</span>'.
-                                       '</li>';
-                        }
+                    } elsif ($item eq 'linkprot') {
+                        $output .= &store_linkprot($cdom,$cnum,'course',$changes->{$item},\%oldlinkprot);
                     } else {
                         if (ref($prefs->{$item}->{'ordered'}) eq 'ARRAY') {
                             my @settings = @{$prefs->{$item}->{'ordered'}};
@@ -2210,6 +2139,156 @@
     return $output;
 }
 
+sub store_linkprot {
+    my ($cdom,$cnum,$context,$changes,$oldlinkprot) = @_;
+    my ($ltiauth,$lti_save_error,$output,$error,%ltienc, at deletions);
+    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 (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 $chome = &Apache::lonnet::homeserver($cnum,$cdom);
+    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 (($chome eq 'no_host') || ($chome 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 (($chome eq 'no_host') || ($chome eq '')) {
+                    if (grep(/^\Q$chome\E$/, at 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}.': '.('*' x $length).', ';
+                                    } else {
+                                        $display .= $desc{$title}.': '.$ltienc{$id}{$title}.', ';
+                                    }
+                                }
+                            }
+                        } elsif ($title eq 'version') {
+                            if ($values{$title} eq 'LTI-1p0') {
+                                $display .= $desc{$title}.': 1.1, ';
+                            }
+                        } else {
+                            $display .= $desc{$title}.': '.$values{$title}.', ';
+                        }
+                    }
+                    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 {
     my ($cnum,$cdom,$chome,$need_env_update,$storehash)  = @_;
     my $count = 0;
@@ -2549,70 +2628,12 @@
 }
 ENDSCRIPT
     }
-    my $linkprotector_js = <<"ENDSCRIPT";
-function toggleLTI(form,num,item) {
-    var radioname = '';
-    var currdivid = '';
-    var newdivid = '';
-    if ((document.getElementById('linkprot_divcurr'+item+'_'+num)) &&
-        (document.getElementById('linkprot_divchg'+item+'_'+num))) {
-        currdivid = document.getElementById('linkprot_divcurr'+item+'_'+num);
-        newdivid = document.getElementById('linkprot_divchg'+item+'_'+num);
-        radioname = form.elements['linkprot_change'+item+'_'+num];
-        if (radioname) {
-            if (radioname.length > 0) {
-                var setvis;
-                for (var i=0; i<radioname.length; i++) {
-                    if (radioname[i].checked == true) {
-                        if (radioname[i].value == 1) {
-                            newdivid.style.display = 'inline-block';
-                            currdivid.style.display = 'none';
-                            setvis = 1;
-                        }
-                        break;
-                    }
-                }
-                if (!setvis) {
-                    newdivid.style.display = 'none';
-                    currdivid.style.display = 'inline-block';
-                }
-            }
-        }
-    }
-    return;
-}
-
-function toggleLTIReqUser(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
     $jscript = '<script type="text/javascript" language="Javascript">'."\n".
                '// <![CDATA['."\n".  
                $browse_js."\n".$categorize_js."\n".$loncaparev_js."\n".
                $cloners_js."\n".$instcode_js.
                $syllabus_js."\n".$menuitems_js."\n".
-               $linkprotector_js."\n".'//]]>'."\n".
+               &linkprot_javascript()."\n".'//]]>'."\n".
                '</script>'."\n".$stubrowse_js."\n";
     return $jscript;
 }
@@ -2698,6 +2719,68 @@
 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 {
     my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype,$noedit) = @_;
@@ -5501,7 +5584,7 @@
 }
 
 sub print_linkprotection {
-    my ($cdom,$cnum,$settings,$rowtotal,$crstype,$noedit) = @_;
+    my ($cdom,$cnum,$settings,$rowtotal,$crstype,$noedit,$context) = @_;
     unless (ref($settings) eq 'HASH') {
         return;
     }
@@ -5509,7 +5592,7 @@
     my %linkprotection;
     my $count = 0;
     my $next = 1;
-    my ($datatable,$disabled,$css_class);
+    my ($datatable,$disabled,$css_class,$dest);
     if ($noedit) {
         $disabled = ' disabled="disabled"';
     }
@@ -5521,23 +5604,43 @@
     my $itemcount = 0;
 
     my $ltiauth;
-    if (exists($env{'course.'.$env{'request.course.id'}.'.internal.ltiauth'})) {
-        $ltiauth = $env{'course.'.$env{'request.course.id'}.'.internal.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 {
-        my %domdefs = &Apache::lonnet::get_domain_defaults($cdom);
-        $ltiauth = $domdefs{'crsltiauth'};
+        $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);
+        }
     }
-    my $switchserver = &check_switchserver($cdom,$cnum);
 
-    if (ref($settings->{'linkprotection'}) eq 'HASH') {
-        if (keys(%{$settings->{'linkprotection'}})) {
-            my @current = sort { $a <=> $b } keys(%{$settings->{'linkprotection'}});
+    if (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->{'linkprotection'}->{$num}) eq 'HASH') {
-                    %values = %{$settings->{'linkprotection'}->{$num}};
+                if (ref($settings->{'linkprot'}->{$num}) eq 'HASH') {
+                    %values = %{$settings->{'linkprot'}->{$num}};
                 } else {
                     next;
                 }
@@ -5553,7 +5656,7 @@
                 my ($usersty,$onclickrequser,%checkedrequser);
                 if ($ltiauth) {
                     $usersty = 'display:none';
-                    $onclickrequser = ' onclick="toggleLTIReqUser(this.form,'."'requser','optional','1','block','$i'".');"';
+                    $onclickrequser = ' onclick="toggleLinkProtReqUser(this.form,'."'requser','optional','1','block','$i'".');"';
                     %checkedrequser = (
                         no => ' checked="checked"',
                         yes  => '',
@@ -5604,25 +5707,25 @@
                         $datatable .= '<div id="linkprot_divcurrsecret_'.$i.'" style="display:inline-block" /><span class="LC_nobreak">'.
                                       $desc{'secret'}.': ['.&mt('not shown').'] '.(' 'x2).'</span></div>'.
                                       '<span class="LC_nobreak">'.&mt('Change secret?').
-                                      '<label><input type="radio" value="0" name="linkprot_changesecret_'.$i.'" onclick="javascript:toggleLTI(this.form,'."'$i','secret'".');" checked="checked"'.$disabled.' />'.&mt('No').'</label>'.
+                                      '<label><input type="radio" value="0" name="linkprot_changesecret_'.$i.'" onclick="javascript:toggleLinkProt(this.form,'."'$i','secret'".');" checked="checked"'.$disabled.' />'.&mt('No').'</label>'.
                                       (' 'x2).
-                                      '<label><input type="radio" value="1" name="linkprot_changesecret_'.$i.'" onclick="javascript:toggleLTI(this.form,'."'$i','secret'".');" '.$disabled.' />'.&mt('Yes').'</label>'.(' 'x2).
+                                      '<label><input type="radio" value="1" name="linkprot_changesecret_'.$i.'" onclick="javascript:toggleLinkProt(this.form,'."'$i','secret'".');" '.$disabled.' />'.&mt('Yes').'</label>'.(' 'x2).
                                       '</span><div id="linkprot_divchgsecret_'.$i.'" style="display:none" />'.
-                                      '<span class="LC_nobreak"> - '.&mt("submit from course's home server: [_1].",$switchserver).'</span>'.
+                                      '<span class="LC_nobreak"> - '.$switchmessage.'</span>'.
                                       '</div>';
                     } elsif ($values{'key'} eq '') {
-                        $datatable .= '<span class="LC_nobreak">'.&mt('Key and Secret are required').' - '.&mt("submit from course's home server: [_1].",$switchserver).'</span>'."\n";
+                        $datatable .= '<span class="LC_nobreak">'.&mt('Key and Secret are required').' - '.$switchmessage.'</span>'."\n";
                     } else {
-                        $datatable .= '<span class="LC_nobreak">'.&mt('Secret required').' - '.&mt("submit from course's home server: [_1].",$switchserver).'</span>'."\n";
+                        $datatable .= '<span class="LC_nobreak">'.&mt('Secret required').' - '.$switchmessage.'</span>'."\n";
                     }
                 } else {
                     if ($values{'usable'} ne '') {
                         $datatable .= '<div id="linkprot_divcurrsecret_'.$i.'" style="display:inline-block" /><span class="LC_nobreak">'.
                                       $desc{'secret'}.': ['.&mt('not shown').'] '.(' 'x2).'</span></div>'.
                                       '<span class="LC_nobreak">'.&mt('Change?').
-                                      '<label><input type="radio" value="0" name="linkprot_changesecret_'.$i.'" onclick="javascript:toggleLTI(this.form,'."'$i','secret'".');" checked="checked"'.$disabled.' />'.&mt('No').'</label>'.
+                                      '<label><input type="radio" value="0" name="linkprot_changesecret_'.$i.'" onclick="javascript:toggleLinkProt(this.form,'."'$i','secret'".');" checked="checked"'.$disabled.' />'.&mt('No').'</label>'.
                                       (' 'x2).
-                                      '<label><input type="radio" value="1" name="linkprot_changesecret_'.$i.'" onclick="javascript:toggleLTI(this.form,'."'$i','secret'".');"'.$disabled.' />'.&mt('Yes').
+                                      '<label><input type="radio" value="1" name="linkprot_changesecret_'.$i.'" onclick="javascript:toggleLinkProt(this.form,'."'$i','secret'".');"'.$disabled.' />'.&mt('Yes').
                                       '</label>  </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.' />'.
@@ -5656,7 +5759,7 @@
     my ($usersty,$onclickrequser,%checkedrequser);
     if ($ltiauth) {
         $usersty = 'display:none';
-        $onclickrequser = ' onclick="toggleLTIReqUser(this.form,'."'requser','optional','1','block','add'".');"';
+        $onclickrequser = ' onclick="toggleLinkProtReqUser(this.form,'."'requser','optional','1','block','add'".');"';
         %checkedrequser = (
             no => ' checked="checked"',
             yes  => '',
@@ -5679,7 +5782,7 @@
     }
     $datatable .= '<br /><br />';
     if ($switchserver) {
-        $datatable .= '<span class="LC_nobreak">'.&mt('Key and Secret are required').' - '.&mt("submit from course's home server: [_1].",$switchserver).'</span>'."\n";
+        $datatable .= '<span class="LC_nobreak">'.&mt('Key and Secret are required').' - '.$switchmessage.'</span>'."\n";
     } else {
         $datatable .= '<span class="LC_nobreak">'.$desc{'key'}.':<input type="text" size="25" name="linkprot_key_add" value="" autocomplete="off"'.$disabled.' /></span> '."\n".
                       (' 'x2).
@@ -5714,16 +5817,20 @@
 }
 
 sub check_switchserver {
-    my ($cdom,$cnum) = @_;
-    my ($allowed,$switchserver);
-    my $home = &Apache::lonnet::homeserver($cnum,$cdom);
-    unless ($home eq 'no_host') {
+    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.'&role='.
                           &HTML::Entities::encode($env{'request.role'},'\'<>"&').
-                          '&destinationurl=/adm/courseprefs">'.&mt('Switch Server').'</a>';
+                          '&destinationurl='.$dest.'">'.&mt('Switch Server').'</a>';
         }
     }
     return $switchserver;
@@ -5755,7 +5862,7 @@
             $checked{'auth'} = ' checked="checked"';
         }
     }
-    my $onclickuser = ' onclick="toggleLTIReqUser(this.form,'."'mapuser','userfield','other','inline-block','$num'".');"';
+    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').': ';
     foreach my $option ('sourcedid','email','other') {


More information about the LON-CAPA-cvs mailing list