--- loncom/interface/courseprefs.pm 2022/09/08 01:41:13 1.115
+++ loncom/interface/courseprefs.pm 2023/04/13 15:21:00 1.119
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Handler to set configuration settings for a course
#
-# $Id: courseprefs.pm,v 1.115 2022/09/08 01:41:13 raeburn Exp $
+# $Id: courseprefs.pm,v 1.119 2023/04/13 15:21:00 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -225,6 +225,7 @@ use Apache::courseclassifier;
use Apache::lonlocal;
use LONCAPA qw(:DEFAULT :match);
use Crypt::CBC;
+use Time::HiRes qw( sleep );
my $registered_cleanup;
my $modified_courses;
@@ -372,6 +373,8 @@ sub handler {
my %values=&Apache::lonnet::dump('environment',$cdom,$cnum);
my %linkprot=&Apache::lonnet::dump('lti',$cdom,$cnum,undef,undef,undef,1);
my %ltienc = &Apache::lonnet::dump('nohist_ltienc',$cdom,$cnum,undef,undef,undef,1);
+ my %ltitools = &Apache::lonnet::dump('ltitools',$cdom,$cnum,undef,undef,undef,1);
+ my %ltitoolsenc = &Apache::lonnet::dump('nohist_toolsenc',$cdom,$cnum,undef,undef,undef,1);
foreach my $id (keys(%linkprot)) {
if (ref($linkprot{$id}) eq 'HASH') {
if (ref($ltienc{$id}) eq 'HASH') {
@@ -389,11 +392,27 @@ sub handler {
if ($linkprot{'lock'}) {
delete($linkprot{'lock'});
}
+ foreach my $id (keys(%ltitools)) {
+ if (ref($ltitools{$id}) eq 'HASH') {
+ if (ref($ltitoolsenc{$id}) eq 'HASH') {
+ $values{'ltitools'}{$id} = { %{$ltitools{$id}}, %{$ltitoolsenc{$id}} };
+ } else {
+ $values{'ltitools'}{$id} = $ltitools{$id};
+ }
+ }
+ unless ($phase eq 'process') {
+ if (ref($values{'ltitools'}{$id}) eq 'HASH') {
+ delete($values{'ltitools'}{$id}{'secret'});
+ }
+ }
+ }
+ if ($ltitools{'lock'}) {
+ delete($ltitools{'lock'});
+ }
my @prefs_order = ('courseinfo','localization','feedback','discussion',
'classlists','appearance','grading','printouts',
- 'menuitems','linkprot','spreadsheet','bridgetasks',
- 'lti','other');
-
+ 'menuitems','ltitools','linkprot','spreadsheet',
+ 'bridgetasks','lti','other');
my %prefs = (
'courseinfo' =>
{ text => $lt{'gens'},
@@ -593,6 +612,14 @@ sub handler {
col2 => 'Settings',
}],
},
+ 'ltitools' =>
+ {
+ text => 'External tools',
+ help => 'Course_Prefs_ExternalTools',
+ header => [{col1 => 'Item',
+ col2 => 'Settings',
+ }],
+ },
'other' =>
{ text => 'Other settings',
help => 'Course_Prefs_Other',
@@ -800,6 +827,12 @@ sub print_config_box {
$output .= &print_spreadsheet($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype,$noedit);
} elsif ($action eq 'bridgetasks') {
$output .= &print_bridgetasks($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype,$noedit);
+ } elsif ($action eq 'ltitools') {
+ my $currtools = {};
+ if ((ref($settings) eq 'HASH') && (ref($settings->{'ltitools'}))) {
+ $currtools = $settings->{'ltitools'};
+ }
+ $output .= &print_ltitools($cdom,$cnum,$currtools,\$rowtotal,$crstype,$noedit,'course');
} elsif ($action eq 'lti') {
$output .= &print_lti($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype,$noedit);
} elsif ($action eq 'menuitems') {
@@ -836,7 +869,7 @@ sub process_changes {
}
}
}
- } elsif ($action eq 'linkprot') {
+ } elsif (($action eq 'linkprot') || ($action eq 'ltitools')) {
if (ref($values->{$action}) eq 'HASH') {
foreach my $id (keys(%{$values->{$action}})) {
if ($id =~ /^\d+$/) {
@@ -845,8 +878,8 @@ sub process_changes {
}
}
@ordered = sort { $a <=> $b } @ordered;
- if (($env{'form.linkprot_add'}) && ($env{'form.linkprot_maxnum'} =~ /^\d+$/)) {
- push(@ordered,$env{'form.linkprot_maxnum'});
+ if (($env{'form.'.$action.'_add'}) && ($env{'form.'.$action.'_maxnum'} =~ /^\d+$/)) {
+ push(@ordered,$env{'form.'.$action.'_maxnum'});
}
} elsif (ref($item->{'ordered'}) eq 'ARRAY') {
if ($action eq 'courseinfo') {
@@ -989,6 +1022,12 @@ sub process_changes {
if (ref($values) eq 'HASH') {
$errors = &process_linkprot($cdom,$cnum,$values->{$action},$changes,'course',$lastactref);
}
+ } elsif ($action eq 'ltitools') {
+ if (ref($values) eq 'HASH') {
+ my $switchserver = &check_switchserver($cdom,$cnum,'course','/adm/courseprefs');
+ $errors = &process_ltitools('',$cdom,$cnum,$values->{$action},$changes,'course',$lastactref,
+ 'ok','','ok');
+ }
} else {
foreach my $entry (@ordered) {
if ($entry eq 'cloners') {
@@ -1528,7 +1567,7 @@ sub process_changes {
sub process_linkprot {
my ($cdom,$cnum,$values,$changes,$context,$lastactref) = @_;
- my ($home,$dest,$ltiauth,$privkey,$privnum,$cipher,$errors,%linkprot);
+ my ($dest,$ltiauth,$privnum,$cipher,$errors,%linkprot);
if (ref($values) eq 'HASH') {
foreach my $id (keys(%{$values})) {
if ($id =~ /^\d+$/) {
@@ -1538,31 +1577,7 @@ sub process_linkprot {
}
}
}
- my %domdefs = &Apache::lonnet::get_domain_defaults($cdom);
- my @ids=&Apache::lonnet::current_machine_ids();
- if ($context eq 'domain') {
- $home = &Apache::lonnet::domain($cdom,'primary');
- } else {
- $home = &Apache::lonnet::homeserver($cnum,$cdom);
- }
- if ((($context eq 'domain') && ($domdefs{'linkprotenc_dom'})) ||
- (($context eq 'course') && ($domdefs{'linkprotenc_crs'}))) {
- unless (($home eq 'no_host') || ($home eq '')) {
- if (grep(/^\Q$home\E$/,@ids)) {
- if (ref($domdefs{'privhosts'}) eq 'ARRAY') {
- if (grep(/^\Q$home\E$/,@{$domdefs{'privhosts'}})) {
- my %privhash = &Apache::lonnet::restore_dom('lti','private',$cdom,$home,1);
- $privkey = $privhash{'key'};
- $privnum = $privhash{'version'};
- if (($privnum) && ($privkey ne '')) {
- $cipher = Crypt::CBC->new({'key' => $privkey,
- 'cipher' => 'DES'});
- }
- }
- }
- }
- }
- }
+ ($cipher,$privnum) = &get_credentials($cdom,$cnum,'lti',$context);
if ($context eq 'domain') {
$dest = '/adm/domainprefs';
$ltiauth = 1;
@@ -1815,6 +1830,671 @@ sub get_linkprot_id {
return ($id,$error);
}
+sub get_credentials {
+ my ($cdom,$cnum,$type,$context) = @_;
+ my ($cipher,$privnum,$home);
+ my %domdefs = &Apache::lonnet::get_domain_defaults($cdom);
+ my @ids=&Apache::lonnet::current_machine_ids();
+ if ($context eq 'domain') {
+ $home = &Apache::lonnet::domain($cdom,'primary');
+ } else {
+ $home = &Apache::lonnet::homeserver($cnum,$cdom);
+ }
+ my ($hostskey,$domkey,$crskey);
+ if ($type eq 'ltitools') {
+ $hostskey = 'toolprivhosts';
+ $domkey = 'toolenc_dom';
+ $crskey = 'toolenc_crs';
+ } else {
+ $hostskey = 'ltiprivhosts';
+ $domkey = 'linkprotenc_dom';
+ $crskey = 'linkprotenc_crs';
+ }
+ if ((($context eq 'domain') && ($domdefs{$domkey})) ||
+ (($context eq 'course') && ($domdefs{$crskey}))) {
+ unless (($home eq 'no_host') || ($home eq '')) {
+ if (grep(/^\Q$home\E$/,@ids)) {
+ if (ref($domdefs{$hostskey}) eq 'ARRAY') {
+ if (grep(/^\Q$home\E$/,@{$domdefs{$hostskey}})) {
+ my %privhash = &Apache::lonnet::restore_dom($type,'private',$cdom,$home,1);
+ my $privkey = $privhash{'key'};
+ $privnum = $privhash{'version'};
+ if (($privnum) && ($privkey ne '')) {
+ $cipher = Crypt::CBC->new({'key' => $privkey,
+ 'cipher' => 'DES'});
+ }
+ }
+ }
+ }
+ }
+ }
+ return ($cipher,$privnum);
+}
+
+sub process_ltitools {
+ my ($r,$cdom,$cnum,$values,$changes,$context,$lastactref,$configuserok,$lonhost,
+ $author_ok,$confname) = @_;
+ my (%currconfig,$newid,@allpos,%changes,%ltitools,$errors);
+
+ my (%posslti,%possfield);
+ my @courseroles = ('cc','in','ta','ep','st');
+ my @ltiroles = qw(Instructor ContentDeveloper TeachingAssistant Learner);
+ map { $posslti{$_} = 1; } @ltiroles;
+ my @allfields = ('fullname','firstname','lastname','email','user','roles');
+ map { $possfield{$_} = 1; } @allfields;
+
+ my ($dest,$privnum,$cipher,$errors,%ltitools);
+
+ ($cipher,$privnum) = &get_credentials($cdom,$cnum,'ltitools',$context);
+ if ($context eq 'domain') {
+ $dest = '/adm/domainprefs';
+ } else {
+ $dest = '/adm/courseprefs';
+ }
+ my $switchserver = &check_switchserver($cdom,$cnum,$context,$dest);
+
+ my (@allpos,@items,%deletions,%itemids,%haschanges);
+ if ($env{'form.ltitools_add'}) {
+ my $title = $env{'form.ltitools_add_title'};
+ $title =~ s/(`)/'/g;
+ my ($newid,$error) = &get_ltitools_id($context,$cdom,$cnum,$title);
+ if ($newid) {
+ my $position = $env{'form.ltitools_add_pos'};
+ $position =~ s/\D+//g;
+ if ($position ne '') {
+ $allpos[$position] = $newid;
+ }
+ $haschanges{$newid} = 1;
+ foreach my $item ('title','url','lifetime') {
+ $env{'form.ltitools_add_'.$item} =~ s/(`)/'/g;
+ if ($item eq 'lifetime') {
+ $env{'form.ltitools_add_'.$item} =~ s/[^\d.]//g;
+ }
+ if ($env{'form.ltitools_add_'.$item}) {
+ $ltitools{$newid}{$item} = $env{'form.ltitools_add_'.$item};
+ }
+ }
+ if ($env{'form.ltitools_add_version'} eq 'LTI-1p0') {
+ $ltitools{$newid}{'version'} = $env{'form.ltitools_add_version'};
+ }
+ if ($env{'form.ltitools_add_msgtype'} eq 'basic-lti-launch-request') {
+ $ltitools{$newid}{'msgtype'} = $env{'form.ltitools_add_msgtype'};
+ }
+ if ($env{'form.ltitools_add_sigmethod'} eq 'HMAC-SHA256') {
+ $ltitools{$newid}{'sigmethod'} = $env{'form.ltitools_add_sigmethod'};
+ } else {
+ $ltitools{$newid}{'sigmethod'} = 'HMAC-SHA1';
+ }
+ foreach my $item ('width','height','linktext','explanation') {
+ $env{'form.ltitools_add_'.$item} =~ s/^\s+//;
+ $env{'form.ltitools_add_'.$item} =~ s/\s+$//;
+ if (($item eq 'width') || ($item eq 'height')) {
+ if ($env{'form.ltitools_add_'.$item} =~ /^\d+$/) {
+ $ltitools{$newid}{'display'}{$item} = $env{'form.ltitools_add_'.$item};
+ }
+ } else {
+ if ($env{'form.ltitools_add_'.$item} ne '') {
+ $ltitools{$newid}{'display'}{$item} = $env{'form.ltitools_add_'.$item};
+ }
+ }
+ }
+ if ($env{'form.ltitools_add_target'} eq 'window') {
+ $ltitools{$newid}{'display'}{'target'} = $env{'form.ltitools_add_target'};
+ } elsif ($env{'form.ltitools_add_target'} eq 'tab') {
+ $ltitools{$newid}{'display'}{'target'} = $env{'form.ltitools_add_target'};
+ } else {
+ $ltitools{$newid}{'display'}{'target'} = 'iframe';
+ }
+ foreach my $item ('passback','roster') {
+ if ($env{'form.ltitools_'.$item.'_add'}) {
+ $ltitools{$newid}{$item} = 1;
+ if ($env{'form.ltitools_'.$item.'valid_add'} ne '') {
+ my $lifetime = $env{'form.ltitools_'.$item.'valid_add'};
+ $lifetime =~ s/^\s+|\s+$//g;
+ if ($lifetime =~ /^\d+\.?\d*$/) {
+ $ltitools{$newid}{$item.'valid'} = $lifetime;
+ }
+ }
+ }
+ }
+ if ($env{'form.ltitools_add_image.filename'} ne '') {
+ my ($imageurl,$error) =
+ &process_ltitools_image($r,$context,$cdom,$cnum,$confname,'ltitools_add_image',
+ $newid,$configuserok,$lonhost,$author_ok);
+ if ($imageurl) {
+ $ltitools{$newid}{'image'} = $imageurl;
+ }
+ if ($error) {
+ &Apache::lonnet::logthis($error);
+ $errors .= '
'.$error.'';
+ }
+ }
+ my @fields = &Apache::loncommon::get_env_multiple('form.ltitools_add_fields');
+ foreach my $field (@fields) {
+ if ($possfield{$field}) {
+ if ($field eq 'roles') {
+ foreach my $role (@courseroles) {
+ my $choice = $env{'form.ltitools_add_roles_'.$role};
+ if (($choice ne '') && ($posslti{$choice})) {
+ $ltitools{$newid}{'roles'}{$role} = $choice;
+ if ($role eq 'cc') {
+ $ltitools{$newid}{'roles'}{'co'} = $choice;
+ }
+ }
+ }
+ } else {
+ $ltitools{$newid}{'fields'}{$field} = 1;
+ }
+ }
+ }
+ if (ref($ltitools{$newid}{'fields'}) eq 'HASH') {
+ if ($ltitools{$newid}{'fields'}{'user'}) {
+ if ($env{'form.ltitools_add_userincdom'}) {
+ $ltitools{$newid}{'incdom'} = 1;
+ }
+ }
+ }
+ my @courseconfig = &Apache::loncommon::get_env_multiple('form.ltitools_add_courseconfig');
+ foreach my $item (@courseconfig) {
+ $ltitools{$newid}{'crsconf'}{$item} = 1;
+ }
+ if ($env{'form.ltitools_add_custom'}) {
+ my $name = $env{'form.ltitools_add_custom_name'};
+ my $value = $env{'form.ltitools_add_custom_value'};
+ $value =~ s/(`)/'/g;
+ $name =~ s/(`)/'/g;
+ $ltitools{$newid}{'custom'}{$name} = $value;
+ }
+ unless ($switchserver) {
+ my $keyitem = 'form.ltitools_add_key';
+ $env{$keyitem} =~ s/(`)/'/g;
+ if ($env{$keyitem} ne '') {
+ $ltitools{$newid}{'key'} = $env{$keyitem};
+ }
+ my $secretitem = 'form.ltitools_secret_add';
+ $env{$secretitem} =~ s/(`)/'/g;
+ if ($env{$secretitem} ne '') {
+ if ($privnum && $cipher) {
+ $ltitools{$newid}{'secret'} = $cipher->encrypt_hex($env{$secretitem});
+ $ltitools{$newid}{'cipher'} = $privnum;
+ } else {
+ $ltitools{$newid}{'secret'} = $env{$secretitem};
+ }
+ }
+ }
+ } else {
+ $errors .= ''.
+ &mt('Failed to acquire unique ID for new external tool').
+ '';
+ }
+ }
+ if (ref($values) eq 'HASH') {
+ my %deletions;
+ my @todelete = &Apache::loncommon::get_env_multiple('form.ltitools_del');
+ if (@todelete) {
+ map { $deletions{$_} = 1; } @todelete;
+ }
+ my %customadds;
+ my @newcustom = &Apache::loncommon::get_env_multiple('form.ltitools_customadd');
+ if (@newcustom) {
+ map { $customadds{$_} = 1; } @newcustom;
+ }
+ my %imgdeletions;
+ my @todeleteimages = &Apache::loncommon::get_env_multiple('form.ltitools_image_del');
+ if (@todeleteimages) {
+ map { $imgdeletions{$_} = 1; } @todeleteimages;
+ }
+ my $maxnum = $env{'form.ltitools_maxnum'};
+ for (my $i=0; $i<=$maxnum; $i++) {
+ my $itemid = $env{'form.ltitools_id_'.$i};
+ $itemid =~ s/\D+//g;
+ if (ref($values->{$itemid}) eq 'HASH') {
+ if ($deletions{$itemid}) {
+ if ($values->{$itemid}{'image'}) {
+ #FIXME need to obsolete item in RES space
+ }
+ $haschanges{$itemid} = $values->{$itemid}{'title'};
+ next;
+ } else {
+ my $newpos = $env{'form.ltitools_'.$itemid};
+ $newpos =~ s/\D+//g;
+ foreach my $item ('title','url','lifetime') {
+ $ltitools{$itemid}{$item} = $env{'form.ltitools_'.$item.'_'.$i};
+ if ($values->{$itemid}{$item} ne $ltitools{$itemid}{$item}) {
+ $haschanges{$itemid} = 1;
+ }
+ }
+ if ($env{'form.ltitools_version_'.$i} eq 'LTI-1p0') {
+ $ltitools{$itemid}{'version'} = $env{'form.ltitools_version_'.$i};
+ }
+ if ($env{'form.ltitools_msgtype_'.$i} eq 'basic-lti-launch-request') {
+ $ltitools{$itemid}{'msgtype'} = $env{'form.ltitools_msgtype_'.$i};
+ }
+ if ($env{'form.ltitools_sigmethod_'.$i} eq 'HMAC-SHA256') {
+ $ltitools{$itemid}{'sigmethod'} = $env{'form.ltitools_sigmethod_'.$i};
+ } else {
+ $ltitools{$itemid}{'sigmethod'} = 'HMAC-SHA1';
+ }
+ if ($values->{$itemid}{'sigmethod'} eq '') {
+ if ($ltitools{$itemid}{'sigmethod'} ne 'HMAC-SHA1') {
+ $haschanges{$itemid} = 1;
+ }
+ } elsif ($values->{$itemid}{'sigmethod'} ne $ltitools{$itemid}{'sigmethod'}) {
+ $haschanges{$itemid} = 1;
+ }
+ foreach my $size ('width','height') {
+ $env{'form.ltitools_'.$size.'_'.$i} =~ s/^\s+//;
+ $env{'form.ltitools_'.$size.'_'.$i} =~ s/\s+$//;
+ if ($env{'form.ltitools_'.$size.'_'.$i} =~ /^\d+$/) {
+ $ltitools{$itemid}{'display'}{$size} = $env{'form.ltitools_'.$size.'_'.$i};
+ if (ref($values->{$itemid}{'display'}) eq 'HASH') {
+ if ($values->{$itemid}{'display'}{$size} ne $ltitools{$itemid}{'display'}{$size}) {
+ $haschanges{$itemid} = 1;
+ }
+ } else {
+ $haschanges{$itemid} = 1;
+ }
+ } elsif (ref($values->{$itemid}{'display'}) eq 'HASH') {
+ if ($values->{$itemid}{'display'}{$size} ne '') {
+ $haschanges{$itemid} = 1;
+ }
+ }
+ }
+ foreach my $item ('linktext','explanation') {
+ $env{'form.ltitools_'.$item.'_'.$i} =~ s/^\s+//;
+ $env{'form.ltitools_'.$item.'_'.$i} =~ s/\s+$//;
+ if ($env{'form.ltitools_'.$item.'_'.$i} ne '') {
+ $ltitools{$itemid}{'display'}{$item} = $env{'form.ltitools_'.$item.'_'.$i};
+ if (ref($values->{$itemid}{'display'}) eq 'HASH') {
+ if ($values->{$itemid}{'display'}{$item} ne $ltitools{$itemid}{'display'}{$item}) {
+ $haschanges{$itemid} = 1;
+ }
+ } else {
+ $haschanges{$itemid} = 1;
+ }
+ } elsif (ref($values->{$itemid}{'display'}) eq 'HASH') {
+ if ($values->{$itemid}{'display'}{$item} ne '') {
+ $haschanges{$itemid} = 1;
+ }
+ }
+ }
+ if ($env{'form.ltitools_target_'.$i} eq 'window') {
+ $ltitools{$itemid}{'display'}{'target'} = $env{'form.ltitools_target_'.$i};
+ } elsif ($env{'form.ltitools_target_'.$i} eq 'tab') {
+ $ltitools{$itemid}{'display'}{'target'} = $env{'form.ltitools_target_'.$i};
+ } else {
+ $ltitools{$itemid}{'display'}{'target'} = 'iframe';
+ }
+ if (ref($values->{$itemid}{'display'}) eq 'HASH') {
+ if ($values->{$itemid}{'display'}{'target'} ne $ltitools{$itemid}{'display'}{'target'}) {
+ $haschanges{$itemid} = 1;
+ }
+ } else {
+ $haschanges{$itemid} = 1;
+ }
+ foreach my $extra ('passback','roster') {
+ if ($env{'form.ltitools_'.$extra.'_'.$i}) {
+ $ltitools{$itemid}{$extra} = 1;
+ if ($env{'form.ltitools_'.$extra.'valid_'.$i} ne '') {
+ my $lifetime = $env{'form.ltitools_'.$extra.'valid_'.$i};
+ $lifetime =~ s/^\s+|\s+$//g;
+ if ($lifetime =~ /^\d+\.?\d*$/) {
+ $ltitools{$itemid}{$extra.'valid'} = $lifetime;
+ }
+ }
+ }
+ if ($values->{$itemid}{$extra} ne $ltitools{$itemid}{$extra}) {
+ $haschanges{$itemid} = 1;
+ }
+ if ($values->{$itemid}{$extra.'valid'} ne $ltitools{$itemid}{$extra.'valid'}) {
+ $haschanges{$itemid} = 1;
+ }
+ }
+ my @courseconfig = &Apache::loncommon::get_env_multiple('form.ltitools_courseconfig_'.$i);
+ foreach my $item ('label','title','target','linktext','explanation','append') {
+ if (grep(/^\Q$item\E$/,@courseconfig)) {
+ $ltitools{$itemid}{'crsconf'}{$item} = 1;
+ if (ref($values->{$itemid}{'crsconf'}) eq 'HASH') {
+ if ($values->{$itemid}{'crsconf'}{$item} ne $ltitools{$itemid}{'crsconf'}{$item}) {
+ $haschanges{$itemid} = 1;
+ }
+ } else {
+ $haschanges{$itemid} = 1;
+ }
+ }
+ }
+ my @fields = &Apache::loncommon::get_env_multiple('form.ltitools_fields_'.$i);
+ foreach my $field (@fields) {
+ if ($possfield{$field}) {
+ if ($field eq 'roles') {
+ foreach my $role (@courseroles) {
+ my $choice = $env{'form.ltitools_roles_'.$role.'_'.$i};
+ if (($choice ne '') && ($posslti{$choice})) {
+ $ltitools{$itemid}{'roles'}{$role} = $choice;
+ if ($role eq 'cc') {
+ $ltitools{$itemid}{'roles'}{'co'} = $choice;
+ }
+ }
+ if (ref($values->{$itemid}{'roles'}) eq 'HASH') {
+ if ($values->{$itemid}{'roles'}{$role} ne $ltitools{$itemid}{'roles'}{$role}) {
+ $haschanges{$itemid} = 1;
+ }
+ } elsif ($ltitools{$itemid}{'roles'}{$role}) {
+ $haschanges{$itemid} = 1;
+ }
+ }
+ } else {
+ $ltitools{$itemid}{'fields'}{$field} = 1;
+ if (ref($values->{$itemid}{'fields'}) eq 'HASH') {
+ if ($values->{$itemid}{'fields'}{$field} ne $ltitools{$itemid}{'fields'}{$field}) {
+ $haschanges{$itemid} = 1;
+ }
+ } else {
+ $haschanges{$itemid} = 1;
+ }
+ }
+ }
+ }
+ if (ref($ltitools{$itemid}{'fields'}) eq 'HASH') {
+ if ($ltitools{$itemid}{'fields'}{'user'}) {
+ if ($env{'form.ltitools_userincdom_'.$i}) {
+ $ltitools{$itemid}{'incdom'} = 1;
+ }
+ if ($values->{$itemid}{'incdom'} ne $ltitools{$itemid}{'incdom'}) {
+ $haschanges{$itemid} = 1;
+ }
+ }
+ }
+ $allpos[$newpos] = $itemid;
+ }
+ if ($imgdeletions{$itemid}) {
+ $haschanges{$itemid} = 1;
+ if ($context eq 'course') {
+ my $currimgurl = $values->{$itemid}{'image'};
+ if ($currimgurl =~ m{^(\Q/uploaded/$cdom/$cnum/toollogo/$itemid\E)/([^/]+)$}) {
+ my ($path,$imagefile) = ($1,$2);
+ if ($imagefile =~ /^tn\-(.+)$/) {
+ my $origimg = $1;
+ &Apache::lonnet::removeuploadedurl("$path/$origimg");
+ }
+ &Apache::lonnet::removeuploadedurl($currimgurl);
+ }
+ }
+ #FIXME need to obsolete item in RES space
+ } elsif ($env{'form.ltitools_image_'.$i.'.filename'}) {
+ my $currimgurl = $values->{$itemid}{'image'};
+ my ($imgurl,$error) = &process_ltitools_image($r,$context,$cdom,$cnum,$confname,'ltitools_image_'.$i,
+ $itemid,$configuserok,$lonhost,$author_ok,$currimgurl);
+ if ($imgurl) {
+ $ltitools{$itemid}{'image'} = $imgurl;
+ $haschanges{$itemid} = 1;
+ }
+ if ($error) {
+ &Apache::lonnet::logthis($error);
+ $errors .= ''.$error.'';
+ }
+ } elsif ($values->{$itemid}{'image'}) {
+ $ltitools{$itemid}{'image'} = $values->{$itemid}{'image'};
+ }
+ if ($customadds{$i}) {
+ my $name = $env{'form.ltitools_custom_name_'.$i};
+ $name =~ s/(`)/'/g;
+ $name =~ s/^\s+//;
+ $name =~ s/\s+$//;
+ my $value = $env{'form.ltitools_custom_value_'.$i};
+ $value =~ s/(`)/'/g;
+ $value =~ s/^\s+//;
+ $value =~ s/\s+$//;
+ if ($name ne '') {
+ $ltitools{$itemid}{'custom'}{$name} = $value;
+ $haschanges{$itemid} = 1;
+ }
+ }
+ my %customdels;
+ my @customdeletions = &Apache::loncommon::get_env_multiple('form.ltitools_customdel_'.$i);
+ if (@customdeletions) {
+ $haschanges{$itemid} = 1;
+ }
+ map { $customdels{$_} = 1; } @customdeletions;
+ if (ref($values->{$itemid}{'custom'}) eq 'HASH') {
+ foreach my $key (keys(%{$values->{$itemid}{'custom'}})) {
+ unless ($customdels{$key}) {
+ if ($env{'form.ltitools_customval_'.$key.'_'.$i} ne '') {
+ $ltitools{$itemid}{'custom'}{$key} = $env{'form.ltitools_customval_'.$key.'_'.$i};
+ }
+ if ($values->{$itemid}{'custom'}{$key} ne $env{'form.ltitools_customval_'.$key.'_'.$i}) {
+ $haschanges{$itemid} = 1;
+ }
+ }
+ }
+ }
+ unless ($switchserver) {
+ my $keyitem = 'form.ltitools_key_'.$i;
+ $env{$keyitem} =~ s/(`)/'/g;
+ if ($values->{$itemid}{'key'} ne $env{$keyitem}) {
+ $haschanges{$itemid} = 1;
+ }
+ if ($env{$keyitem} ne '') {
+ $ltitools{$itemid}{'key'} = $env{$keyitem};
+ }
+ my $secretitem = 'form.ltitools_secret_'.$i;
+ $env{$secretitem} =~ s/(`)/'/g;
+ if ($values->{$itemid}{'usable'}) {
+ if ($env{'form.ltitools_changesecret_'.$i}) {
+ if ($env{$secretitem} ne '') {
+ if ($privnum && $cipher) {
+ $ltitools{$itemid}{'secret'} = $cipher->encrypt_hex($env{$secretitem});
+ $ltitools{$itemid}{'cipher'} = $privnum;
+ } else {
+ $ltitools{$itemid}{'secret'} = $env{$secretitem};
+ }
+ $haschanges{$itemid} = 1;
+ }
+ } else {
+ $ltitools{$itemid}{'secret'} = $values->{$itemid}{'secret'};
+ $ltitools{$itemid}{'cipher'} = $values->{$itemid}{'cipher'};
+ }
+ } elsif ($env{$secretitem} ne '') {
+ if ($privnum && $cipher) {
+ $ltitools{$itemid}{'secret'} = $cipher->encrypt_hex($env{$secretitem});
+ $ltitools{$itemid}{'cipher'} = $privnum;
+ } else {
+ $ltitools{$itemid}{'secret'} = $env{$secretitem};
+ }
+ $haschanges{$itemid} = 1;
+ }
+ }
+ unless ($haschanges{$itemid}) {
+ foreach my $key (keys(%{$values->{$itemid}})) {
+ if (ref($values->{$itemid}{$key}) eq 'HASH') {
+ if (ref($ltitools{$itemid}{$key}) eq 'HASH') {
+ foreach my $innerkey (keys(%{$values->{$itemid}{$key}})) {
+ unless (exists($ltitools{$itemid}{$key}{$innerkey})) {
+ $haschanges{$itemid} = 1;
+ last;
+ }
+ }
+ } elsif (keys(%{$values->{$itemid}{$key}}) > 0) {
+ $haschanges{$itemid} = 1;
+ }
+ }
+ last if ($haschanges{$itemid});
+ }
+ }
+ }
+ }
+ }
+ if (@allpos > 0) {
+ my $idx = 0;
+ foreach my $itemid (@allpos) {
+ if ($itemid ne '') {
+ $ltitools{$itemid}{'order'} = $idx;
+ if (ref($values) eq 'HASH') {
+ if (ref($values->{$itemid}) eq 'HASH') {
+ if ($values->{$itemid}{'order'} ne $idx) {
+ $haschanges{$itemid} = 1;
+ }
+ }
+ }
+ $idx ++;
+ }
+ }
+ }
+ if (keys(%haschanges)) {
+ foreach my $entry (keys(%haschanges)) {
+ $changes->{$entry} = $ltitools{$entry};
+ }
+ if (ref($lastactref) eq 'HASH') {
+ $lastactref->{'courseltitools'} = 1;
+ }
+ }
+ return $errors;
+}
+
+sub get_ltitools_id {
+ my ($context,$cdom,$cnum,$title) = @_;
+ my ($lockhash,$tries,$gotlock,$id,$error);
+
+ # get lock on ltitools db
+ $lockhash = {
+ lock => $env{'user.name'}.
+ ':'.$env{'user.domain'},
+ };
+ $tries = 0;
+ if ($context eq 'domain') {
+ $gotlock = &Apache::lonnet::newput_dom('ltitools',$lockhash,$cdom);
+ } else {
+ $gotlock = &Apache::lonnet::newput('ltitools',$lockhash,$cdom,$cnum);
+ }
+ while (($gotlock ne 'ok') && ($tries<10)) {
+ $tries ++;
+ sleep (0.1);
+ if ($context eq 'domain') {
+ $gotlock = &Apache::lonnet::newput_dom('ltitools',$lockhash,$cdom);
+ } else {
+ $gotlock = &Apache::lonnet::newput('ltitools',$lockhash,$cdom,$cnum);
+ }
+ }
+ if ($gotlock eq 'ok') {
+ my %currids;
+ if ($context eq 'domain') {
+ %currids = &Apache::lonnet::dump_dom('ltitools',$cdom);
+ } else {
+ %currids = &Apache::lonnet::dump('ltitools',$cdom,$cnum);
+ }
+ if ($currids{'lock'}) {
+ delete($currids{'lock'});
+ if (keys(%currids)) {
+ my @curr = sort { $a <=> $b } keys(%currids);
+ if ($curr[-1] =~ /^\d+$/) {
+ $id = 1 + $curr[-1];
+ }
+ } else {
+ $id = 1;
+ }
+ if ($id) {
+ if ($context eq 'domain') {
+ unless (&Apache::lonnet::newput_dom('ltitools',{ $id => $title },$cdom) eq 'ok') {
+ $error = 'nostore';
+ }
+ } else {
+ unless (&Apache::lonnet::newput('ltitools',{ $id => $title },$cdom,$cnum) eq 'ok') {
+ $error = 'nostore';
+ }
+ }
+ } else {
+ $error = 'nonumber';
+ }
+ }
+ my $dellockoutcome;
+ if ($context eq 'domain') {
+ $dellockoutcome = &Apache::lonnet::del_dom('ltitools',['lock'],$cdom);
+ } else {
+ $dellockoutcome = &Apache::lonnet::del('ltitools',['lock'],$cdom,$cnum);
+ }
+ } else {
+ $error = 'nolock';
+ }
+ return ($id,$error);
+}
+
+sub process_ltitools_image {
+ my ($r,$context,$dom,$cnum,$confname,$caller,$itemid,$configuserok,$switch,$author_ok,$currimg) = @_;
+ my $filename = $env{'form.'.$caller.'.filename'};
+ my ($error,$url);
+ my ($width,$height) = (21,21);
+ if ($configuserok eq 'ok') {
+ if ($switch) {
+ $error = &mt('Upload of Tool Provider (LTI) icon is not permitted to this server: [_1]',
+ $switch);
+ } elsif ($author_ok eq 'ok') {
+ my ($result,$imageurl,$madethumb);
+ if ($context eq 'domain') {
+ ($result,$imageurl,$madethumb) =
+ &Apache::lonconfigsettings::publishlogo($r,'upload',$caller,$dom,$confname,
+ "ltitools/$itemid/icon",$width,$height);
+ } else {
+ ($result,$imageurl,$madethumb) = &processlogo($dom,$cnum,$caller,$currimg,$itemid,$width,$height);
+ }
+ if ($result eq 'ok') {
+ if ($madethumb) {
+ my ($path,$imagefile) = ($imageurl =~ m{^(.+)/([^/]+)$});
+ my $imagethumb = "$path/tn-".$imagefile;
+ $url = $imagethumb;
+ } else {
+ $url = $imageurl;
+ }
+ } else {
+ if ($context eq 'domain') {
+ $error = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",$filename,$result);
+ } else {
+ $error = &mt("Upload of [_1] failed because an error occurred. Error was: [_2].",$filename,$result);
+ }
+ }
+ } else {
+ $error = &mt("Upload of [_1] failed because an author role could not be assigned to a Domain Configuration user ([_2]) in domain: [_3]. Error was: [_4].",$filename,$confname,$dom,$author_ok);
+ }
+ } else {
+ $error = &mt("Upload of [_1] failed because a Domain Configuration user ([_2]) could not be created in domain: [_3]. Error was: [_4].",$filename,$confname,$dom,$configuserok);
+ }
+ return ($url,$error);
+}
+
+sub processlogo {
+ my ($dom,$cnum,$caller,$currimg,$itemid,$width,$height) = @_;
+ my ($result,$imageurl,$madethumb);
+ if ($env{"form.$caller.filename"} ne '') {
+ unless ($caller eq 'ltitools_add_image') {
+ if ($currimg =~ m{^(\Q/uploaded/$dom/$cnum/toollogo/$itemid\E)/([^/]+)$}) {
+ my ($path,$imagefile) = ($1,$2);
+ if ($imagefile =~ /^tn\-(.+)$/) {
+ my $origimg = $1;
+ &Apache::lonnet::removeuploadedurl("$path/$origimg");
+ }
+ &Apache::lonnet::removeuploadedurl($currimg);
+ }
+ }
+ $imageurl = &Apache::lonnet::userfileupload($caller,'toollogo',"toollogo/$itemid",
+ '','','',$cnum,$dom,$width,$height);
+ if ($imageurl =~ m{^(\Q/uploaded/$dom/$cnum/toollogo/$itemid\E)/([^/]+)$}) {
+ my ($path,$imagefile) = ($1,$2);
+ $result = 'ok';
+ my $thumburl = "$path/tn-".$imagefile;
+ my ($rtncode,$info);
+ my $res = &Apache::lonnet::getuploaded('HEAD',$thumburl,$dom,$cnum,\$info,\$rtncode);
+ if ($res eq 'ok') {
+ $madethumb = 1;
+ }
+ } elsif ($imageurl eq '/adm/notfound.html') {
+ undef($imageurl);
+ $result = 'store failed';
+ } elsif ($imageurl =~ /^error: (.+)$/) {
+ $result = $1;
+ }
+ }
+ return ($result,$imageurl,$madethumb);
+}
+
sub get_sec_str {
my ($entry,$num) = @_;
my @secs = &Apache::loncommon::get_env_multiple('form.'.$entry.'_sections_'.$num);
@@ -1857,12 +2537,15 @@ sub check_clone {
sub store_changes {
my ($cdom,$cnum,$prefs_order,$actions,$prefs,$values,$changes,$crstype) = @_;
my ($chome,$output);
- my (%storehash,@delkeys,@need_env_update,@oldcloner,%oldlinkprot);
+ my (%storehash,@delkeys,@need_env_update,@oldcloner,%oldlinkprot,%oldltitools);
if ((ref($values) eq 'HASH') && (ref($changes) eq 'HASH')) {
if (ref($values->{'linkprot'}) eq 'HASH') {
%oldlinkprot = %{$values->{'linkprot'}};
}
delete($values->{'linkprot'});
+ if (ref($values->{'ltitools'}) eq 'HASH') {
+ %oldltitools = %{$values->{'ltitools'}};
+ }
%storehash = %{$values};
} else {
if ($crstype eq 'Community') {
@@ -1877,6 +2560,8 @@ sub store_changes {
$numchanges = scalar(keys(%{$changes}));
if (($numchanges == 1) && (exists($changes->{'linkprot'}))) {
$skipstore = 1;
+ } elsif (($numchanges == 1) && (exists($changes->{'ltitools'}))) {
+ $skipstore = 1;
} elsif (!$numchanges) {
if ($crstype eq 'Community') {
$output = &mt('No changes made to community settings.');
@@ -1913,6 +2598,8 @@ sub store_changes {
}
} elsif ($item eq 'linkprot') {
$output .= &store_linkprot($cdom,$cnum,'course',$changes->{$item},\%oldlinkprot);
+ } elsif ($item eq 'ltitools') {
+ $output .= &store_ltitools($cdom,$cnum,'course',$changes->{$item},\%oldltitools);
} else {
if (ref($prefs->{$item}->{'ordered'}) eq 'ARRAY') {
my @settings = @{$prefs->{$item}->{'ordered'}};
@@ -2477,6 +3164,214 @@ sub store_linkprot {
return $output;
}
+sub store_ltitools {
+ my ($cdom,$cnum,$context,$changes,$oldltitools) = @_;
+ my ($home,$ltitools_save_error,$output,$error,%toolsenc,@deletions);
+ my %lt = <itools_names();
+ my @courseroles = ('cc','in','ta','ep','st');
+ my @allfields = ('fullname','firstname','lastname','email','user','roles');
+ if ($context eq 'domain') {
+ $home = &Apache::lonnet::domain($cdom,'primary');
+ } else {
+ $home = &Apache::lonnet::homeserver($cnum,$cdom);
+ }
+ if (ref($changes) eq 'HASH') {
+ foreach my $id (sort { $a <=> $b } keys(%{$changes})) {
+ if (ref($changes->{$id}) eq 'HASH') {
+ if (exists($changes->{$id}->{'key'})) {
+ $toolsenc{$id}{'key'} = $changes->{$id}->{'key'};
+ delete($changes->{$id}->{'key'});
+ }
+ if (exists($changes->{$id}->{'secret'})) {
+ $toolsenc{$id}{'secret'} = $changes->{$id}->{'secret'};
+ delete($changes->{$id}->{'secret'});
+ } elsif (ref($oldltitools->{$id}) eq 'HASH') {
+ if (exists($oldltitools->{$id}{'usable'})) {
+ $changes->{$id}->{'usable'} = 1;
+ }
+ if (exists($oldltitools->{$id}{'cipher'})) {
+ $changes->{$id}->{'cipher'} = $oldltitools->{$id}{'cipher'};
+ }
+ }
+ }
+ }
+ }
+ my @ids=&Apache::lonnet::current_machine_ids();
+ if (keys(%toolsenc) > 0) {
+ unless (($home eq 'no_host') || ($home eq '')) {
+ my $allowed;
+ foreach my $id (@ids) { if ($id eq $home) { $allowed=1; } }
+ if ($allowed) {
+ if (($context eq 'domain') ||
+ (($context eq 'course') &&
+ (&Apache::lonnet::put('nohist_toolsenc',\%toolsenc,$cdom,$cnum,1) eq 'ok'))) {
+ foreach my $id (keys(%toolsenc)) {
+ if (exists($toolsenc{$id}{'secret'})) {
+ $changes->{$id}->{'usable'} = 1;
+ }
+ }
+ } else {
+ $ltitools_save_error = 1;
+ }
+ }
+ }
+ }
+ unless ($ltitools_save_error) {
+ if ($context eq 'course') {
+ if (&Apache::lonnet::put('ltitools',$changes,$cdom,$cnum,1) eq 'ok') {
+ my $hashid=$cdom.'_'.$cnum;
+ &Apache::lonnet::devalidate_cache_new('courseltitools',$hashid);
+ unless (($home eq 'no_host') || ($home eq '')) {
+ if (grep(/^\Q$home\E$/,@ids)) {
+ &Apache::lonnet::devalidate_cache_new('courseltitoolsenc',$hashid);
+ }
+ }
+ } else {
+ $ltitools_save_error = 1;
+ }
+ }
+ unless ($ltitools_save_error) {
+ my %bynum;
+ foreach my $itemid (sort(keys(%{$changes}))) {
+ my $position = $changes->{$itemid}{'order'};
+ $bynum{$position} = $itemid;
+ }
+ foreach my $pos (sort { $a <=> $b } keys(%bynum)) {
+ my $itemid = $bynum{$pos};
+ if (ref($changes->{$itemid}) ne 'HASH') {
+ $output .= ''.&mt('Deleted: [_1]',$changes->{$itemid}).'';
+ } else {
+ $output .= ''.$changes->{$itemid}{'title'}.'';
+ if ($changes->{$itemid}{'image'}) {
+ $output .= ' '.
+ '
';
+ }
+ $output .= '';
+ my $position = $pos + 1;
+ $output .= '- '.&mt('Order: [_1]',$position).'
';
+ foreach my $item ('version','msgtype','sigmethod','url','lifetime') {
+ if ($changes->{$itemid}{$item} ne '') {
+ $output .= '- '.$lt{$item}.': '.$changes->{$itemid}{$item}.'
';
+ }
+ }
+ if (ref($toolsenc{$itemid}) eq 'HASH') {
+ foreach my $item ('key','secret') {
+ if (exists($toolsenc{$itemid}{$item})) {
+ if ($item eq 'secret') {
+ $output .= '- '.$lt{$item}.': ['.&mt('not shown').']
';
+ } else {
+ $output .= '- '.$lt{$item}.': '.$toolsenc{$itemid}{$item}.'
';
+ }
+ }
+ }
+ }
+ $output .= '- '.&mt('Configurable in course:');
+ my @possconfig = ('label','title','target','linktext','explanation','append');
+ my $numconfig = 0;
+ if (ref($changes->{$itemid}{'crsconf'}) eq 'HASH') {
+ foreach my $item (@possconfig) {
+ if ($changes->{$itemid}{'crsconf'}{$item}) {
+ $numconfig ++;
+ $output .= ' "'.$lt{'crs'.$item}.'"';
+ }
+ }
+ }
+ if (!$numconfig) {
+ $output .= ' '.&mt('None');
+ }
+ $output .= '
';
+ foreach my $item ('passback','roster') {
+ $output .= '- '.$lt{$item}.' ';
+ if ($changes->{$itemid}{$item}) {
+ $output .= &mt('Yes');
+ if ($changes->{$itemid}{$item.'valid'}) {
+ if ($item eq 'passback') {
+ $output .= ' '.&mt('valid for at least [quant,_1,day] after launch',
+ $changes->{$itemid}{$item.'valid'});
+ } else {
+ $output .= ' '.&mt('valid for at least [quant,_1,second] after launch',
+ $changes->{$itemid}{$item.'valid'});
+ }
+ }
+ } else {
+ $output .= &mt('No');
+ }
+ $output .= '
';
+ }
+ if (ref($changes->{$itemid}{'display'}) eq 'HASH') {
+ my $displaylist;
+ if ($changes->{$itemid}{'display'}{'target'}) {
+ $displaylist = &mt('Display target').': '.
+ $changes->{$itemid}{'display'}{'target'}.',';
+ }
+ foreach my $size ('width','height') {
+ if ($changes->{$itemid}{'display'}{$size}) {
+ $displaylist .= (' 'x2).$lt{$size}.': '.
+ $changes->{$itemid}{'display'}{$size}.',';
+ }
+ }
+ if ($displaylist) {
+ $displaylist =~ s/,$//;
+ $output .= '- '.$displaylist.'
';
+ }
+ foreach my $item ('linktext','explanation') {
+ if ($changes->{$itemid}{'display'}{$item}) {
+ $output .= '- '.$lt{$item}.': '.$changes->{$itemid}{'display'}{$item}.'
';
+ }
+ }
+ }
+ if (ref($changes->{$itemid}{'fields'}) eq 'HASH') {
+ my $fieldlist;
+ foreach my $field (@allfields) {
+ if ($changes->{$itemid}{'fields'}{$field}) {
+ $fieldlist .= (' 'x2).$lt{$field}.',';
+ }
+ }
+ if ($fieldlist) {
+ $fieldlist =~ s/,$//;
+ if ($changes->{$itemid}{'fields'}{'user'}) {
+ if ($changes->{$itemid}{'incdom'}) {
+ $fieldlist .= ' ('.&mt('username:domain').')';
+ } else {
+ $fieldlist .= ' ('.&mt('username').')';
+ }
+ }
+ $output .= '- '.&mt('Data sent').':'.$fieldlist.'
';
+ }
+ }
+ if (ref($changes->{$itemid}{'roles'}) eq 'HASH') {
+ my $rolemaps;
+ foreach my $role (@courseroles) {
+ if ($changes->{$itemid}{'roles'}{$role}) {
+ $rolemaps .= (' 'x2).&Apache::lonnet::plaintext($role,'Course').'='.
+ $changes->{$itemid}{'roles'}{$role}.',';
+ }
+ }
+ if ($rolemaps) {
+ $rolemaps =~ s/,$//;
+ $output .= '- '.&mt('Role mapping:').$rolemaps.'
';
+ }
+ }
+ if (ref($changes->{$itemid}{'custom'}) eq 'HASH') {
+ my $customlist;
+ if (keys(%{$changes->{$itemid}{'custom'}})) {
+ foreach my $key (sort(keys(%{$changes->{$itemid}{'custom'}}))) {
+ $customlist .= $key.':'.$changes->{$itemid}{'custom'}{$key}.(' 'x2);
+ }
+ }
+ if ($customlist) {
+ $output .= '- '.&mt('Custom items').': '.$customlist.'
';
+ }
+ }
+ $output .= '
';
+ }
+ }
+ }
+ }
+ return $output;
+}
+
sub update_env {
my ($cnum,$cdom,$chome,$need_env_update,$storehash) = @_;
my $count = 0;
@@ -2613,6 +3508,11 @@ sub get_jscript {
my $stubrowse_js = &Apache::loncommon::studentbrowser_javascript();
my $browse_js = &Apache::loncommon::browser_and_searcher_javascript('parmset');
my $cloners_js = &cloners_javascript($phase);
+ my $currltitools;
+ if (ref($settings) eq 'HASH') {
+ $currltitools = $settings->{'ltitools'};
+ }
+ my $ltitools_js = &Apache::lonconfigsettings::ltitools_javascript($currltitools);
my @code_order;
if ($crstype ne 'Community') {
if (ref($settings) eq 'HASH') {
@@ -2864,7 +3764,7 @@ ENDSCRIPT
$cloners_js."\n".$instcode_js."\n".$localization_js."\n".
$syllabus_js."\n".$menuitems_js."\n".$extresource_js."\n".
&linkprot_javascript()."\n".'//]]>'."\n".
- ''."\n".$stubrowse_js."\n";
+ ''."\n".$stubrowse_js."\n".$ltitools_js."\n";
return $jscript;
}
@@ -2951,38 +3851,6 @@ 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'.
&mt('Requirements for specific folders or resources').
'';
@@ -5452,6 +6307,523 @@ sub print_bridgetasks {
return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype,'bridgetasks',$noedit);
}
+sub print_ltitools {
+ my ($cdom,$cnum,$settings,$rowtotal,$crstype,$noedit,$context) = @_;
+ my ($datatable,$disabled,$css_class,$dest);
+ my %lt = <itools_names();
+ my $itemcount = 1;
+ my $maxnum = 0;
+ my %ordered;
+ if (ref($settings) eq 'HASH') {
+ foreach my $item (keys(%{$settings})) {
+ if (ref($settings->{$item}) eq 'HASH') {
+ my $num = $settings->{$item}{'order'};
+ $ordered{$num} = $item;
+ }
+ }
+ }
+
+ if ($context eq 'domain') {
+ $dest = '/adm/domainprefs';
+ } else {
+ $dest = '/adm/courseprefs';
+ }
+ my ($switchserver,$switchmessage);
+ $switchserver = &check_switchserver($cdom,$cnum,$context,$dest);
+ if ($switchserver) {
+ if ($context eq 'domain') {
+ $switchmessage = &mt("submit from domain's primary library server: [_1].",$switchserver);
+ } elsif ($crstype eq 'Community') {
+ $switchmessage = &mt("submit from community's home server: [_1].",$switchserver);
+ } else {
+ $switchmessage = &mt("submit from course's home server: [_1].",$switchserver);
+ }
+ }
+ my $maxnum = scalar(keys(%ordered));
+ my @courseroles = ('cc','in','ta','ep','st');
+ my @ltiroles = qw(Instructor ContentDeveloper TeachingAssistant Learner);
+ my @fields = ('fullname','firstname','lastname','email','roles','user');
+ if (keys(%ordered)) {
+ my @items = sort { $a <=> $b } keys(%ordered);
+ for (my $i=0; $i<@items; $i++) {
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ my $item = $ordered{$items[$i]};
+ my ($title,$key,$url,$usable,$lifetime,$imgsrc,%sigsel);
+ if (ref($settings->{$item}) eq 'HASH') {
+ $title = $settings->{$item}->{'title'};
+ $url = $settings->{$item}->{'url'};
+ $key = $settings->{$item}->{'key'};
+ $usable = $settings->{$item}->{'usable'};
+ $lifetime = $settings->{$item}->{'lifetime'};
+ my $image = $settings->{$item}->{'image'};
+ if ($image ne '') {
+ $imgsrc = '
';
+ }
+ if ($settings->{$item}->{'sigmethod'} eq 'HMAC-256') {
+ $sigsel{'HMAC-256'} = ' selected="selected"';
+ } else {
+ $sigsel{'HMAC-SHA1'} = ' selected="selected"';
+ }
+ }
+ my $chgstr = ' onchange="javascript:reorderLTITools(this.form,'."'ltitools_".$item."'".');"';
+ $datatable .= ''
+ .''.(' 'x2).
+ ' | '.
+ ''.
+ ''.
+ '';
+ my (%checkedfields,%rolemaps,$userincdom);
+ if (ref($settings->{$item}) eq 'HASH') {
+ if (ref($settings->{$item}->{'fields'}) eq 'HASH') {
+ %checkedfields = %{$settings->{$item}->{'fields'}};
+ }
+ $userincdom = $settings->{$item}->{'incdom'};
+ if (ref($settings->{$item}->{'roles'}) eq 'HASH') {
+ %rolemaps = %{$settings->{$item}->{'roles'}};
+ $checkedfields{'roles'} = 1;
+ }
+ }
+ $datatable .= ''.
+ '';
+ my %courseconfig;
+ if (ref($settings->{$item}) eq 'HASH') {
+ if (ref($settings->{$item}->{'crsconf'}) eq 'HASH') {
+ %courseconfig = %{$settings->{$item}->{'crsconf'}};
+ }
+ }
+ $datatable .= ''.
+ ' |
'."\n";
+ $itemcount ++;
+ }
+ }
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ my $chgstr = ' onchange="javascript:reorderLTITools(this.form,'."'ltitools_add_pos'".');"';
+ $datatable .= ''."\n".
+ ''."\n".
+ ' '."\n".
+ ''.&mt('Add').' | '."\n".
+ ''.
+ ''.
+ ''.
+ '';
+ $datatable .= ''.
+ ''.
+ ''."\n".
+ ' | '."\n".
+ '
'."\n";
+ $itemcount ++;
+ return $datatable;
+}
+
+sub ltitools_names {
+ my %lt = &Apache::lonlocal::texthash(
+ 'title' => 'Title',
+ 'version' => 'Version',
+ 'msgtype' => 'Message Type',
+ 'sigmethod' => 'Signature Method',
+ 'url' => 'URL',
+ 'key' => 'Key',
+ 'lifetime' => 'Nonce lifetime (s)',
+ 'secret' => 'Secret',
+ 'icon' => 'Icon',
+ 'user' => 'User',
+ 'fullname' => 'Full Name',
+ 'firstname' => 'First Name',
+ 'lastname' => 'Last Name',
+ 'email' => 'E-mail',
+ 'roles' => 'Role',
+ 'window' => 'Window',
+ 'tab' => 'Tab',
+ 'iframe' => 'iFrame',
+ 'height' => 'Height',
+ 'width' => 'Width',
+ 'linktext' => 'Default Link Text',
+ 'explanation' => 'Default Explanation',
+ 'passback' => 'Tool can return grades:',
+ 'roster' => 'Tool can retrieve roster:',
+ 'crstarget' => 'Display target',
+ 'crslabel' => 'Course label',
+ 'crstitle' => 'Course title',
+ 'crslinktext' => 'Link Text',
+ 'crsexplanation' => 'Explanation',
+ 'crsappend' => 'Provider URL',
+ );
+ return %lt;
+}
+
sub print_lti {
my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype,$noedit) = @_;
unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
@@ -5969,9 +7341,9 @@ sub print_linkprotection {
$datatable .= ''.
$desc{'secret'}.': ['.&mt('not shown').'] '.(' 'x2).''.
''.&mt('Change secret?').
- ''.
+ ''.
(' 'x2).
- ''.(' 'x2).
+ ''.(' 'x2).
''.
' - '.$switchmessage.''.
'';
@@ -5986,18 +7358,18 @@ sub print_linkprotection {
$datatable .= ''.
$desc{'secret'}.': ['.&mt('not shown').'] '.(' 'x2).''.
''.&mt('Change?').
- ''.
+ ''.
(' 'x2).
- ''.
''.&mt('New Secret').':'.
- ''.
+ ''.
''.&mt('Visible input').''.
'';
} else {
$datatable .=
''.$desc{'secret'}.':'.
- ''.
+ ''.
''.&mt('Visible input').''.
'';
}
@@ -6061,7 +7433,7 @@ sub print_linkprotection {
} else {
$datatable .= ''.$desc{'key'}.': '."\n".
(' 'x2).
- ''.$desc{'secret'}.':'.
+ ''.$desc{'secret'}.':'.
''.&mt('Visible input').' '."\n";
}
$datatable .= '
'.