--- loncom/interface/londocs.pm 2017/08/14 14:54:29 1.635 +++ loncom/interface/londocs.pm 2023/03/27 18:41:04 1.698 @@ -1,7 +1,7 @@ # The LearningOnline Network # Documents # -# $Id: londocs.pm,v 1.635 2017/08/14 14:54:29 raeburn Exp $ +# $Id: londocs.pm,v 1.698 2023/03/27 18:41:04 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -45,6 +45,8 @@ use Apache::lontemplate(); use Apache::lonsimplepage(); use Apache::lonhomework(); use Apache::lonpublisher(); +use Apache::lonparmset(); +use Apache::loncourserespicker(); use HTML::Entities; use HTML::TokeParser; use GDBM_File; @@ -52,6 +54,7 @@ use File::MMagic; use File::Copy; use Apache::lonlocal; use Cwd; +use UUID::Tiny ':std'; use LONCAPA qw(:DEFAULT :match); my $iconpath; @@ -88,7 +91,7 @@ sub storemap { if ($map =~ /^default/) { $hadchanges=1; - } else { + } elsif ($contentchg) { $suppchanges=1; } return ($errtext,0); @@ -180,6 +183,64 @@ sub default_folderpath { } } +sub validate_supppath { + my ($coursenum,$coursedom) = @_; + my $backto; + if ($env{'form.supppath'} ne '') { + my @items = split(/\&/,$env{'form.supppath'}); + my ($badpath,$got_supp,$supppath,%supphidden,%suppids); + for (my $i=0; $i<@items; $i++) { + my $odd = $i%2; + if ((!$odd) && ($items[$i] !~ /^supplemental(|_\d+)$/)) { + $badpath = 1; + last; + } elsif ($odd) { + my $suffix; + my $idx = $i-1; + if ($items[$i] =~ /^([^:]*)::(|1):::$/) { + $backto .= '&'.$1; + } elsif ($items[$idx] eq 'supplemental') { + $backto .= '&'.$items[$i]; + } else { + $backto .= '&'.$items[$i]; + my $is_hidden; + unless ($got_supp) { + my ($supplemental) = &Apache::loncommon::get_supplemental($coursenum,$coursedom); + if (ref($supplemental) eq 'HASH') { + if (ref($supplemental->{'hidden'}) eq 'HASH') { + %supphidden = %{$supplemental->{'hidden'}}; + } + if (ref($supplemental->{'ids'}) eq 'HASH') { + %suppids = %{$supplemental->{'ids'}}; + } + } + $got_supp = 1; + } + if (ref($suppids{"/uploaded/$coursedom/$coursenum/$items[$idx].sequence"}) eq 'ARRAY') { + my $mapid = $suppids{"/uploaded/$coursedom/$coursenum/$items[$idx].sequence"}->[0]; + if ($supphidden{$mapid}) { + $is_hidden = 1; + } + } + $suffix = '::'.$is_hidden.':::'; + } + $supppath .= '&'.$items[$i].$suffix; + } else { + $supppath .= '&'.$items[$i]; + $backto .= '&'.$items[$i]; + } + } + if ($badpath) { + delete($env{'form.supppath'}); + } else { + $supppath =~ s/^\&//; + $backto =~ s/^\&//; + $env{'form.supppath'} = $supppath; + } + } + return $backto; +} + sub dumpcourse { my ($r) = @_; my $crstype = &Apache::loncommon::course_type(); @@ -659,7 +720,7 @@ sub group_import { my $marker = $2; my $info = $3; my ($toolid,%toolhash,%toolsettings); - my @extras = ('linktext','explanation','crslabel','crstitle'); + my @extras = ('linktext','explanation','crslabel','crstitle','crsappend'); my @toolinfo = split(/:/,$info); if ($residx) { %toolsettings=&Apache::lonnet::dump('exttool_'.$marker,$coursedom,$coursenum); @@ -669,14 +730,19 @@ sub group_import { } $toolid =~ s/\D//g; ($toolhash{'target'},$toolhash{'width'},$toolhash{'height'}, - $toolhash{'linktext'},$toolhash{'explanation'}, - $toolhash{'crslabel'},$toolhash{'crstitle'}) = @toolinfo; + $toolhash{'linktext'},$toolhash{'explanation'},$toolhash{'crslabel'}, + $toolhash{'crstitle'},$toolhash{'crsappend'},$toolhash{'gradable'}) = @toolinfo; foreach my $item (@extras) { $toolhash{$item} = &unescape($toolhash{$item}); } + if ($folder =~ /^supplemental/) { + delete($toolhash{'gradable'}); + } else { + $toolhash{'gradable'} =~ s/\D+//g; + } if (ref($ltitoolsref) eq 'HASH') { - my @deleted; if (ref($ltitoolsref->{$toolid}) eq 'HASH') { + my @deleted; $toolhash{'id'} = $toolid; if (($toolhash{'target'} eq 'iframe') || ($toolhash{'target'} eq 'tab') || ($toolhash{'target'} eq 'window')) { @@ -751,11 +817,51 @@ sub group_import { } } } + if ($toolhash{'passback'}) { + my $gradesecret = UUID::Tiny::create_uuid_as_string(UUID_V4); + $toolhash{'gradesecret'} = $gradesecret; + $toolhash{'gradesecretdate'} = time; + } + if ($toolhash{'roster'}) { + my $rostersecret = UUID::Tiny::create_uuid_as_string(UUID_V4); + $toolhash{'rostersecret'} = $rostersecret; + $toolhash{'rostersecretdate'} = time; + } + my $changegradable; + if (($residx) && ($folder =~ /^default/)) { + if ($toolsettings{'gradable'}) { + unless (($toolhash{'gradable'}) || (defined($LONCAPA::map::zombies[$residx]))) { + push(@deleted,'gradable'); + $changegradable = 1; + } + } elsif ($toolhash{'gradable'}) { + $changegradable = 1; + } + if (($caller eq 'londocs') && (defined($LONCAPA::map::zombies[$residx]))) { + $changegradable = 1; + if ($toolsettings{'gradable'}) { + $toolhash{'gradable'} = 1; + } + } + } my $putres = &Apache::lonnet::put('exttool_'.$marker,\%toolhash,$coursedom,$coursenum); if ($putres eq 'ok') { if (@deleted) { &Apache::lonnet::del('exttool_'.$marker,\@deleted,$coursedom,$coursenum); - } + } + if (($changegradable) && ($folder =~ /^default/)) { + my $val; + if ($toolhash{'gradable'}) { + $val = 'yes'; + } else { + $val = 'no'; + } + &LONCAPA::map::storeparameter($residx,'parameter_0_gradable',$val, + 'string_yesno'); + &remember_parms($residx,'gradable','set',$val); + } + } else { + return (&mt('Failed to save update to external tool.'),1); } } } @@ -785,26 +891,27 @@ sub group_import { } my $ext = 'false'; if ($url=~m{^http://} || $url=~m{^https://}) { $ext = 'true'; } - $name = &LONCAPA::map::qtunescape($name); - if ($name eq '') { - $name = &LONCAPA::map::qtunescape(&mt('Web Page')); - } if ($url =~ m{^/uploaded/$coursedom/$coursenum/((?:docs|supplemental)/(?:default|\d+))/new\.html$}) { my $filepath = $1; - my $fname = $name; - if ($fname =~ /^\W+$/) { + my $fname; + if ($name eq '') { + $name = &mt('Web Page'); $fname = 'web'; } else { - $fname =~ s/\W/_/g; - } - if (length($fname) > 15) { - $fname = substr($fname,0,14); + $fname = $name; + $fname=&Apache::lonnet::clean_filename($fname); + if ($fname eq '') { + $fname = 'web'; + } elsif (length($fname) > 15) { + $fname = substr($fname,0,14); + } } + my $title = &Apache::loncommon::cleanup_html($name); my $initialtext = &mt('Replace with your own content.'); my $newhtml = <<END; <html> <head> -<title>$name</title> +<title>$title</title> </head> <body bgcolor="#ffffff"> $initialtext @@ -826,6 +933,7 @@ END return (&mt('Failed to save new web page.'),1); } } + $name = &LONCAPA::map::qtunescape($name); $url = &LONCAPA::map::qtunescape($url); $LONCAPA::map::resources[$residx] = join(':', ($name, $url, $ext, 'normal', 'res')); @@ -866,7 +974,6 @@ END &storemap($coursenum, $coursedom, $folder.'.'.$container,1); unless ($fatal) { if ($folder =~ /^supplemental/) { - &Apache::lonnet::get_numsuppfiles($coursenum,$coursedom,1); my ($errtext,$fatal) = &mapread($coursenum,$coursedom, $folder.'.'.$container); } @@ -993,6 +1100,7 @@ sub docs_change_log { 'encrypturl' => 'URL hidden', 'randompick' => 'Randomly pick', 'randomorder' => 'Randomly ordered', + 'gradable' => 'Grade can be assigned to External Tool', 'set' => 'set to', 'del' => 'deleted'); my $filter = &Apache::loncommon::display_filter('docslog')."\n". @@ -1099,8 +1207,14 @@ sub docs_change_log { } $r->print('</ul>'); if ($docslog{$id}{'logentry'}{'parameter_res'}) { - $r->print(&LONCAPA::map::qtescape((split(/\:/,$docslog{$id}{'logentry'}{'parameter_res'}))[0]).':<ul>'); - foreach my $parameter ('randompick','hiddenresource','encrypturl','randomorder') { + my ($title,$url) = split(/\:/,$docslog{$id}{'logentry'}{'parameter_res'},3); + if ($title eq '') { + ($title) = ($url =~ m{/([^/]+)$}); + } elsif ($is_supp) { + $title = &Apache::loncommon::parse_supplemental_title($title); + } + $r->print(&LONCAPA::map::qtescape($title).':<ul>'); + foreach my $parameter ('randompick','hiddenresource','encrypturl','randomorder','gradable') { if ($docslog{$id}{'logentry'}{'parameter_action_'.$parameter}) { # FIXME: internationalization seems wrong here $r->print('<li>'. @@ -1168,13 +1282,19 @@ sub update_paste_buffer { # Construct identifiers for current contents of user's paste buffer if (@currpaste) { foreach my $suffix (@currpaste) { - my $cid = $env{'docs.markedcopy_crs_'.$suffix}; - my $url = $env{'docs.markedcopy_url_'.$suffix}; - my $mapidx = $env{'docs.markedcopy_map_'.$suffix}; - if (($cid =~ /^$match_domain(?:_)$match_courseid$/) && - ($url ne '')) { - $pasteurls{$cid.'_'.$url.'_'.$mapidx} = 1; - } + my $cid = $env{'docs.markedcopy_crs_'.$suffix}; + my $url = $env{'docs.markedcopy_url_'.$suffix}; + my $mapidx = $env{'docs.markedcopy_map_'.$suffix}; + if (($cid =~ /^$match_domain(?:_)$match_courseid$/) && + ($url ne '')) { + if ($url eq '/res/lib/templates/simpleproblem.problem') { + $pasteurls{$cid.'_'.$mapidx} = 1; + } elsif ($url =~ m{^/res/$match_domain/$match_username/}) { + $pasteurls{$url} = 1; + } else { + $pasteurls{$cid.'_'.$url} = 1; + } + } } } @@ -1183,7 +1303,7 @@ sub update_paste_buffer { my @pathitems = split(/\&/,$env{'form.folderpath'}); my @folderconf = split(/\:/,$pathitems[-1]); - my $ispage = $folderconf[4]; + my $ispage = $folderconf[5]; foreach my $item (@possibles) { my ($orderidx,$cmd) = split(/:/,$item); @@ -1196,7 +1316,13 @@ sub update_paste_buffer { $env{'form.folderpath'},\%curr_groups); next if ($denied{'copy'}); $url=~s{http(:|:)//https(:|:)//}{https$2//}; - next if (exists($pasteurls{$coursedom.'_'.$coursenum.'_'.$mapidx})); + if ($url eq '/res/lib/templates/simpleproblem.problem') { + next if (exists($pasteurls{$coursedom.'_'.$coursenum.'_'.$mapidx})); + } elsif ($url =~ m{^/res/$match_domain/$match_username/}) { + next if (exists($pasteurls{$url})); + } else { + next if (exists($pasteurls{$coursedom.'_'.$coursenum.'_'.$url})); + } my ($suffix,$errortxt,$locknotfreed) = &new_timebased_suffix($env{'user.domain'},$env{'user.name'},'paste'); if ($suffix ne '') { @@ -1393,7 +1519,7 @@ sub print_paste_buffer { } $pasteitems .= '<label><input type="checkbox" name="pasting" id="pasting_'.$suffix.'" value="'.$suffix.'" '.$onclick.'/>'.$buffer.'</label>'; if ($nopaste) { - $pasteitems .= $nopaste; + $pasteitems .= ' <span class="LC_cusr_emph">'.$nopaste.'</span>'; } else { if ($othercrs) { $pasteitems .= $othercrs; @@ -1741,7 +1867,7 @@ sub do_paste_from_buffer { %msgs = &Apache::lonlocal::texthash ( notinsupp => 'Paste failed: content type is not supported within Supplemental Content', notincrs => 'Paste failed: Item is from a different course which you do not have rights to edit.', - notindom => 'Paste failed: Item is an external tool from a course in a different donain.', + notindom => 'Paste failed: Item is an external tool from a course in a different domain.', duplicate => 'Paste failed: only one instance of a particular published sequence or page is allowed within each course.', ); @@ -1770,14 +1896,7 @@ sub do_paste_from_buffer { # Retrieve information about all course maps in main content area my $allmaps = {}; - if ($folder =~ /^default/) { - $allmaps = - &Apache::loncommon::allmaps_incourse($coursedom,$coursenum, - $env{"course.$env{'request.course.id'}.home"}, - $env{'request.course.id'}); - } - - my (@toclear,%mapurls,%lockerrs,%msgerrs,%results); + my (@toclear,%mapurls,%lockerrs,%msgerrs,%results,$donechk); # Loop over the items to paste foreach my $suffix (@dopaste) { @@ -1795,6 +1914,13 @@ sub do_paste_from_buffer { if ($is_map{$suffix}) { # If pasting a map, check if map contains other maps my (%hierarchy,%titles); + if (($folder =~ /^default/) && (!$donechk)) { + $allmaps = + &Apache::loncommon::allmaps_incourse($coursedom,$coursenum, + $env{"course.$env{'request.course.id'}.home"}, + $env{'request.course.id'}); + $donechk = 1; + } &contained_map_check($url,$folder,$coursenum,$coursedom, \%removefrommap,\%removeparam,\%addedmaps, \%hierarchy,\%titles,$allmaps); @@ -1852,13 +1978,18 @@ sub do_paste_from_buffer { } if ($url=~ m{/(bulletinboard|smppg|ext\.tool)$}) { my $prefix = $1; - my $fromothercrs; + my $fromothercrs; #need to copy the db contents to a new one, unless this is a move. my %info = ( src => $url, cdom => $coursedom, cnum => $coursenum, ); + if ($prefix eq 'ext.tool') { + if ($prefixchg{$suffix} eq 'docstosupp') { + $info{'delgradable'} = 1; + } + } if (($srcdom{$suffix} =~ /^$match_domain$/) && ($srcnum{$suffix} =~ /^$match_courseid$/)) { unless (($srcdom{$suffix} eq $coursedom) && ($srcnum{$suffix} eq $coursenum)) { $fromothercrs = 1; @@ -1950,6 +2081,18 @@ sub do_paste_from_buffer { ©_templated_files($url,$srcdom{$suffix},$srcnum{$suffix},$srcmapidx{$suffix}, $coursedom,$coursenum,$template,$newidx,"$folder.$container"); } + } elsif ($url =~ /ext\.tool$/) { + if (($newidx) && ($folder=~/^default/)) { + my $marker = (split(m{/},$url))[4]; + my %toolsettings = &Apache::lonnet::dump('exttool_'.$marker,$coursedom,$coursenum); + my $val = 'no'; + if ($toolsettings{'gradable'}) { + $val = 'yes'; + } + &LONCAPA::map::storeparameter($newidx,'parameter_0_gradable',$val, + 'string_yesno'); + &remember_parms($newidx,'gradable','set',$val); + } } $LONCAPA::map::resources[$newidx]=$title.':'.&LONCAPA::map::qtunescape($url). ':'.$ext.':normal:res'; @@ -2198,6 +2341,9 @@ sub dbcopy { } } $db_name =~ s{_\d*$ }{_$suffix}x; + if (($prefix eq 'exttool') && ($dbref->{'delgradable'}) && ($contents{'gradable'})) { + delete($contents{'gradable'}); + } $result=&Apache::lonnet::put($db_name,\%contents, $coursedom,$coursenum); if ($result eq 'ok') { @@ -2260,7 +2406,9 @@ sub copy_templated_files { my @simpleprobqtypes = qw(radio option string essay numerical); my $qtype=$srcparms{$srcprefix.'questiontype'}; if (grep(/^\Q$qtype\E$/,@simpleprobqtypes)) { - my %newdata; + my %newdata = ( + $newprefix.'questiontype' => $qtype, + ); foreach my $type (@simpleprobqtypes) { if ($type eq $qtype) { $newdata{"$weightprefix.$type.weight"}=1; @@ -2482,16 +2630,38 @@ sub url_paste_fixups { $changed = 1; } } - } elsif ($ressrc =~ m{^/adm/($match_domain)/($match_courseid)/.+$}) { + } elsif ($ressrc =~ m{^/adm/($match_domain)/($match_courseid)/(.+)$}) { next if ($skip); my $srcdom = $1; my $srcnum = $2; + my $rem = $3; + my ($is_exttool,$exttoolchg); + if ($rem =~ m{\d+/ext\.tool$}) { + $is_exttool = 1; + } if (($srcdom ne $cdom) || ($srcnum ne $cnum)) { $rewrites->{$oldurl}{$id} = $ressrc; $dbcopies->{$oldurl}{$id}{'src'} = $ressrc; $dbcopies->{$oldurl}{$id}{'cdom'} = $srcdom; $dbcopies->{$oldurl}{$id}{'cnum'} = $srcnum; $changed = 1; + if ($is_exttool) { + $exttoolchg = 1; + } + } elsif (($rem =~ m{\d+/ext\.tool$}) && + ($env{'form.docs.markedcopy_options'} ne 'move')) { + $dbcopies->{$oldurl}{$id}{'src'} = $ressrc; + $dbcopies->{$oldurl}{$id}{'cdom'} = $srcdom; + $dbcopies->{$oldurl}{$id}{'cnum'} = $srcnum; + $changed = 1; + $exttoolchg = 1; + } + if (($is_exttool) && ($prefixchg)) { + if ($oldurl =~ m{^/uploaded/$match_domain/$match_courseid/default}) { + if ($exttoolchg) { + $dbcopies->{$oldurl}{$id}{'delgradable'} = 1; + } + } } } elsif ($ressrc =~ m{^/adm/$match_domain/$match_username/\d+/(smppg|bulletinboard)$}) { if (($fromcdom ne $cdom) || ($fromcnum ne $cnum) || @@ -2654,6 +2824,15 @@ sub apply_fixups { $storefn =~ s/^((?:default|supplemental)_)(\d+)/$1$newsubdir{$key}/; } my $mapcontent = &Apache::lonnet::getfile($key); + if (($mapcontent eq '-1') && ($before{'map'} eq 'supplemental') && + ($after{'map'} eq 'default') && + ($key =~ m{^/uploaded/$match_domain/$match_courseid/supplemental_\d+\.sequence$})) { + $mapcontent = '<map>'."\n". + '<resource id="1" src="" type="start" />'."\n". + '<link from="1" to="2" index="1" />'."\n". + '<resource id="2" src="" type="finish" />'."\n". + '</map>'; + } if ($mapcontent eq '-1') { if (ref($errors) eq 'HASH') { $errors->{$key} = 1; @@ -2712,9 +2891,7 @@ sub apply_fixups { } } if (ref($resdatacopy{$key}) eq 'HASH') { - if ($newsubdir{$key}) { - - } + my ($gotnewmapname,$newmapname,$srcfolder,$srccontainer); foreach my $idx (keys(%{$resdatacopy{$key}})) { if (ref($resdatacopy{$key}{$idx}) eq 'HASH') { my $srcurl = $resdatacopy{$key}{$idx}{'src'}; @@ -2724,15 +2901,18 @@ sub apply_fixups { ($resdatacopy{$key}{$idx}{'cnum'} =~ /^$match_courseid$/)) { my $srcdom = $resdatacopy{$key}{$idx}{'cdom'}; my $srcnum = $resdatacopy{$key}{$idx}{'cnum'}; - my ($newmapname) = ($key =~ m{/([^/]+)$}); - my ($srcfolder,$srccontainer) = split(/\./,$newmapname); + unless ($gotnewmapname) { + ($newmapname) = ($key =~ m{/([^/]+)$}); + ($srcfolder,$srccontainer) = split(/\./,$newmapname); + if ($newsubdir{$key}) { + $newmapname =~ s/^((?:default|supplemental)_)(\d+)/$1$newsubdir{$key}/; + } + $gotnewmapname = 1; + } my $srcmapinfo = $srcfolder.':'.$idx; if ($srccontainer eq 'page') { $srcmapinfo .= ':1'; } - if ($newsubdir{$key}) { - $newmapname =~ s/^((?:default|supplemental)_)(\d+)/$1$newsubdir{$key}/; - } ©_templated_files($srcurl,$srcdom,$srcnum,$srcmapinfo,$cdom, $cnum,$template,$idx,$newmapname); } @@ -2755,7 +2935,8 @@ sub apply_fixups { } } } - for (my $i=0; $i<@LONCAPA::map::order; $i++) { + my $total = scalar(@LONCAPA::map::order) - 1; + for (my $i=$total; $i>=0; $i--) { my $idx = $LONCAPA::map::order[$i]; if (defined($LONCAPA::map::resources[$idx])) { my $changed; @@ -2765,7 +2946,7 @@ sub apply_fixups { splice(@LONCAPA::map::order,$i,1); if (ref($currparam{$idx}) eq 'ARRAY') { foreach my $name (@{$currparam{$idx}}) { - &LONCAPA::map::delparameter($idx,'parameter_'.$name); + &LONCAPA::map::delparameter($idx,$name); } } next; @@ -2807,7 +2988,7 @@ sub apply_fixups { foreach my $idx (keys(%remparam)) { if (ref($remparam{$idx}) eq 'ARRAY') { foreach my $name (@{$remparam{$idx}}) { - &LONCAPA::map::delparameter($idx,'parameter_'.$name); + &LONCAPA::map::delparameter($idx,$name); } } } @@ -2934,7 +3115,7 @@ sub update_parameter { my ($name,$url)=split(/\:/,$LONCAPA::map::resources[$res]); $name=&LONCAPA::map::qtescape($name); $url=&LONCAPA::map::qtescape($url); - next unless ($name && $url); + next unless $url; my $is_map; if ($url =~ m{/uploaded/.+\.(page|sequence)$}) { $is_map = 1; @@ -3386,6 +3567,21 @@ sub editor { $r->print('</div>'); } + if ((!$allowed) && ($folder =~ /^supplemental_\d+$/)) { + my ($supplemental) = &Apache::loncommon::get_supplemental($coursenum,$coursedom); + if (ref($supplemental) eq 'HASH') { + if ((ref($supplemental->{'hidden'}) eq 'HASH') && + (ref($supplemental->{'ids'}) eq 'HASH')) { + if (ref($supplemental->{'ids'}->{"/uploaded/$coursedom/$coursenum/$folder.$container"}) eq 'ARRAY') { + my $mapnum = $supplemental->{'ids'}->{"/uploaded/$coursedom/$coursenum/$folder.$container"}->[0]; + if ($supplemental->{'hidden'}->{$mapnum}) { + $ishidden = 1; + } + } + } + } + } + my ($to_show,$output,@allidx,@allmapidx,%filters,%lists,%curr_groups); %filters = ( canremove => [], @@ -3409,11 +3605,17 @@ sub editor { push(@allmapidx,$res); } + if (($supplementalflag) && (!$allowed) && (!$env{'request.role.adv'})) { + if (($ishidden) || ((&LONCAPA::map::getparameter($res,'parameter_hiddenresource'))[0]=~/^yes$/i)) { + $idx++; + next; + } + } $output .= &entryline($idx,$name,$url,$folder,$allowed,$res, $coursenum,$coursedom,$crstype, $pathitem,$supplementalflag,$container, \%filters,\%curr_groups,$ltitoolsref,$canedit, - $isencrypted,$navmapref,$hostname); + $isencrypted,$ishidden,$navmapref,$hostname); $idx++; $shown++; } @@ -3422,10 +3624,14 @@ sub editor { my $need_save; if ($allowed || ($supplementalflag && $folder eq 'supplemental')) { my $toolslink; - if ($allowed) { + if ($allowed || $canedit) { + my $helpitem = 'Navigation_Screen'; + if (!$allowed) { + $helpitem = 'Supplemental_Navigation'; + } $toolslink = '<table><tr><td>' .&Apache::loncommon::help_open_menu('Navigation Screen', - 'Navigation_Screen',undef,'RAT') + $helpitem,undef,'RAT') .'</td><td class="LC_middle">'.&mt('Tools:').'</td>' .'<td align="left"><ul id="LC_toolbar">' .'<li><a href="/adm/coursedocs?forcesupplement=1&command=editsupp" ' @@ -3441,11 +3647,9 @@ sub editor { .&Apache::loncommon::start_data_table_header_row() .'<th colspan="2">'.&mt('Move').'</th>' .'<th colspan="3">'.&mt('Actions').'</th>' - .'<th>'.&mt('Document').'</th>'; - if ($folder !~ /^supplemental/) { - $to_show .= '<th colspan="2">'.&mt('Settings').'</th>'; - } - $to_show .= &Apache::loncommon::end_data_table_header_row(); + .'<th>'.&mt('Document').'</th>' + .'<th colspan="2">'.&mt('Settings').'</th>' + .&Apache::loncommon::end_data_table_header_row(); if ($folder !~ /^supplemental/) { $lists{'canhide'} = join(',',@allidx); $lists{'canrandomlyorder'} = join(',',@allmapidx); @@ -3793,12 +3997,14 @@ sub is_supplemental_title { sub entryline { my ($index,$title,$url,$folder,$allowed,$residx,$coursenum,$coursedom, $crstype,$pathitem,$supplementalflag,$container,$filtersref,$currgroups, - $ltitoolsref,$canedit,$isencrypted,$navmapref,$hostname)=@_; - my ($foldertitle,$renametitle,$oldtitle); + $ltitoolsref,$canedit,$isencrypted,$ishidden,$navmapref,$hostname)=@_; + my ($foldertitle,$renametitle,$oldtitle,$encodedtitle); if (&is_supplemental_title($title)) { ($title,$foldertitle,$renametitle) = &Apache::loncommon::parse_supplemental_title($title); + $encodedtitle=$title; } else { $title=&HTML::Entities::encode($title,'"<>&\''); + $encodedtitle=$title; $renametitle=$title; $foldertitle=$title; } @@ -3820,7 +4026,7 @@ sub entryline { my $line=&Apache::loncommon::start_data_table_row(); my ($form_start,$form_end,$form_common,$form_param); # Edit commands - my ($esc_path, $path, $symb, $curralias); + my ($esc_path, $path, $symb, $shownsymb, $curralias); if ($env{'form.folderpath'}) { $esc_path=&escape($env{'form.folderpath'}); $path = &HTML::Entities::encode($env{'form.folderpath'},'<>&"'); @@ -4025,6 +4231,7 @@ END my $ispage; my $containerarg; my $folderurl; + my $plainurl; if ($uploaded) { if (($extension eq 'sequence') || ($extension eq 'page')) { $url=~/\Q$coursenum\E\/([\/\w]+)\.\Q$extension\E$/; @@ -4043,18 +4250,26 @@ END $url='/adm/supplemental?'; } } else { - &Apache::lonnet::allowuploaded('/adm/coursedoc',$url); + $plainurl = $url; } } my ($editlink,$extresform,$anchor,$hiddenres,$nomodal); my $orig_url = $url; $orig_url=~s{http(:|:)//https(:|:)//}{https$2//}; - $url=~s{^http(|s)(:|:)//}{/adm/wrapper/ext/}; + if ($container eq 'page') { + $url=~s{^http(|s)(:|:)//}{/ext/}; + } else { + $url=~s{^http(|s)(:|:)//}{/adm/wrapper/ext/}; + } if (!$supplementalflag && $residx && $symb) { if ((!$isfolder) && (!$ispage)) { (undef,undef,$url)=&Apache::lonnet::decode_symb($symb); - $url=&Apache::lonnet::clutter($url); + if (($url =~ m{^ext/}) && ($container eq 'page')) { + $url=&Apache::lonnet::clutter_with_no_wrapper($url); + } else { + $url=&Apache::lonnet::clutter($url); + } if ($url=~/^\/*uploaded\//) { $url=~/\.(\w+)$/; my $embstyle=&Apache::loncommon::fileembstyle($1); @@ -4068,7 +4283,7 @@ END } elsif ($url=~m{^(|/adm/wrapper)/ext/([^#]+)}) { my $wrapped = $1; my $exturl = $2; - if ($wrapped eq '') { + if (($wrapped eq '') && ($container ne 'page')) { $url='/adm/wrapper'.$url; } if (($ENV{'SERVER_PORT'} == 443) && ($exturl !~ /^https:/)) { @@ -4079,37 +4294,16 @@ END } elsif ($url eq "/public/$coursedom/$coursenum/syllabus") { if (($ENV{'SERVER_PORT'} == 443) && ($env{'course.'.$env{'request.course.id'}.'.externalsyllabus'} =~ m{^http://})) { - $url .= '?usehttp=1'; + unless ((&Apache::lonnet::uses_sts()) || (&Apache::lonnet::waf_allssl($hostname))) { + $url .= '?usehttp=1'; + } $nomodal = 1; } } - if (&Apache::lonnet::symbverify($symb,$url)) { - my $shownsymb = $symb; - if ($isexternal) { - if ($url =~ /^([^#]+)#([^#]+)$/) { - $url = $1; - $anchor = $2; - if ($symb =~ m{^([^#]+)\Q#$anchor\E$}) { - $shownsymb = $1.&escape('#').$anchor; - } - } - } - unless ($env{'request.role.adv'}) { - if ((&LONCAPA::map::getparameter($orderidx,'parameter_hiddenresource'))[0]=~/^yes$/i) { - $url = ''; - } - if (&Apache::lonnet::EXT('resource.0.hiddenresource',$symb) =~ /^yes$/i) { - $url = ''; - $hiddenres = 1; - } - } - if ($url ne '') { - $url.=(($url=~/\?/)?'&':'?').'symb='.&HTML::Entities::encode($shownsymb,'"<>&'); - } - } elsif (!$env{'request.role.adv'}) { - my $checkencrypt; + my $checkencrypt; + if (!$env{'request.role.adv'}) { if (((&LONCAPA::map::getparameter($orderidx,'parameter_encrypturl'))[0]=~/^yes$/i) || - $isencrypted || (&Apache::lonnet::EXT('resource.0.encrypturl',$symb) =~ /^yes$/i)) { + ($isencrypted) || (&Apache::lonnet::EXT('resource.0.encrypturl',$symb) =~ /^yes$/i)) { $checkencrypt = 1; } elsif (ref($navmapref)) { unless (ref($$navmapref)) { @@ -4117,26 +4311,44 @@ END } if (ref($$navmapref)) { if (lc($$navmapref->get_mapparam($symb,undef,"0.encrypturl")) eq 'yes') { - $checkencrypt = 1; + $checkencrypt = 1; } } } - if ($checkencrypt) { - my $shownsymb = &Apache::lonenc::encrypted($symb); - my $shownurl = &Apache::lonenc::encrypted($url); - if (&Apache::lonnet::symbverify($shownsymb,$shownurl)) { - $url = $shownurl.(($shownurl=~/\?/)?'&':'?').'symb='.&HTML::Entities::encode($shownsymb,'"<>&'); - if ($env{'request.enc'} ne '') { - delete($env{'request.enc'}); - } - } else { - $url=''; - } + } + if ($checkencrypt) { + my $currenc = $env{'request.enc'}; + $env{'request.enc'} = 1; + $shownsymb = &Apache::lonenc::encrypted($symb); + my $shownurl = &Apache::lonenc::encrypted($url); + if (&Apache::lonnet::symbverify($symb,$url)) { + $url = $shownurl; } else { - $url=''; + $url = ''; + } + $env{'request.enc'} = $currenc; + } elsif (&Apache::lonnet::symbverify($symb,$url)) { + $shownsymb = $symb; + if ($isexternal) { + $url =~ s/\#[^#]+$//; + if ($container eq 'page') { + $url = &Apache::lonnet::clutter($url); + } } } else { - $url=''; + $url = ''; + } + unless ($env{'request.role.adv'}) { + if ((&LONCAPA::map::getparameter($orderidx,'parameter_hiddenresource'))[0]=~/^yes$/i) { + $url = ''; + } + if (&Apache::lonnet::EXT('resource.0.hiddenresource',$symb) =~ /^yes$/i) { + $url = ''; + $hiddenres = 1; + } + } + if (($url ne '') && ($shownsymb ne '')) { + $url .= (($url=~/\?/)?'&':'?').'symb='.&escape($shownsymb); } } } elsif ($supplementalflag) { @@ -4145,8 +4357,11 @@ END $url = $1; $anchor = $2; if (($url =~ m{^(|/adm/wrapper)/ext/(?!https:)}) && ($ENV{'SERVER_PORT'} == 443)) { - if ($hostname ne '') { - $url = 'http://'.$hostname.$url; + unless ((&Apache::lonnet::uses_sts()) || (&Apache::lonnet::waf_allssl($hostname))) { + if ($hostname ne '') { + $url = 'http://'.$hostname.$url; + } + $url .= (($url =~ /\?/) ? '&':'?').'usehttp=1'; } $nomodal = 1; } @@ -4154,12 +4369,30 @@ END } elsif ($url =~ m{^\Q/public/$coursedom/$coursenum/syllabus\E}) { if (($ENV{'SERVER_PORT'} == 443) && ($env{'course.'.$env{'request.course.id'}.'.externalsyllabus'} =~ m{^http://})) { - if ($hostname ne '') { - $url = 'http://'.$hostname.$url; + unless ((&Apache::lonnet::uses_sts()) || (&Apache::lonnet::waf_allssl($hostname))) { + if ($hostname ne '') { + $url = 'http://'.$hostname.$url; + } + $url .= (($url =~ /\?/) ? '&':'?').'usehttp=1'; } - $url .= (($url =~ /\?/) ? '&':'?').'usehttp=1'; $nomodal = 1; } + } elsif (($uploaded) && (!$allowed) && ($url ne '/adm/supplemental?')) { + my $embstyle=&Apache::loncommon::fileembstyle($extension); + unless ($embstyle eq 'ssi') { + if (($embstyle eq 'img') + || ($embstyle eq 'emb') + || ($embstyle eq 'wrp')) { + $url='/adm/wrapper'.$url; + } elsif ($url !~ /\.(sequence|page)$/) { + $url='/adm/coursedocs/showdoc'.$url; + } + } + } + unless ($allowed && $env{'request.role.adv'}) { + if ($ishidden || (&LONCAPA::map::getparameter($orderidx,'parameter_hiddenresource'))[0]=~/^yes$/i) { + $hiddenres = 1; + } } } my ($rand_pick_text,$rand_order_text,$hiddenfolder); @@ -4171,6 +4404,9 @@ END if (!$allowed && $supplementalflag) { $folderpath.=$containerarg.'&'.$foldername; $url.='folderpath='.&escape($folderpath); + if ($ishidden || (&LONCAPA::map::getparameter($orderidx,'parameter_hiddenresource'))[0]=~/^yes$/i) { + $hiddenfolder = 1; + } } else { my $rpicknum = (&LONCAPA::map::getparameter($orderidx, 'parameter_randompick'))[0]; @@ -4256,7 +4492,7 @@ $form_end; $url .= ($url =~ /\?/) ? '&':'?'; $url .= 'folderpath='.&HTML::Entities::encode($esc_path,'<>&"'); if ($title) { - $url .= '&title='.&HTML::Entities::encode($renametitle,'<>&"'); + $url .= '&title='.$encodedtitle; } if ((($isexternal) || ($isexttool)) && $orderidx) { $url .= '&idx='.$orderidx; @@ -4291,7 +4527,7 @@ $form_end; &Apache::lonhtmlcommon::jump_to_editres($cfile,$home, $switchserver, $forceedit, - undef,$symb, + undef,$symb,$shownsymb, &escape($env{'form.folderpath'}), $renametitle,$hostname, '','',1,$suppanchor); @@ -4311,7 +4547,7 @@ $form_end; $reinit = &mt('(re-initialize course to access)'); } $line.='<td class="LC_docs_entry_commands"'.$tdalign.'><span class="LC_nobreak">'.$editlink.$renamelink; - if ($url =~ /$LONCAPA::assess_re/) { + if ($orig_url =~ /$LONCAPA::assess_re/) { $line.= '<br />'; if ($curralias ne '') { $line.='<span class="LC_nobreak"><a href="javascript:delalias('."'$esc_path','$orderidx'".');" class="LC_docs_alias">'. @@ -4322,9 +4558,18 @@ $form_end; } } $line.='</td><td>'; - my $link; + my ($link,$nolink); if (($url=~m{/adm/(coursedocs|supplemental)}) || (!$allowed && $url)) { - $line.='<a href="'.$url.'"><img src="'.$icon.'" alt="" class="LC_icon" /></a>'; + if ($allowed && !$env{'request.role.adv'} && !$isfolder && !$ispage) { + if ((&LONCAPA::map::getparameter($orderidx,'parameter_hiddenresource'))[0]=~/^yes$/i) { + $nolink = 1; + } + } + if ($nolink) { + $line .= '<img src="'.$icon.'" alt="" class="LC_icon" /></a>'; + } else { + $line.='<a href="'.$url.'"><img src="'.$icon.'" alt="" class="LC_icon" /></a>'; + } } elsif ($url) { if ($anchor ne '') { if ($supplementalflag) { @@ -4338,9 +4583,15 @@ $form_end; } else { $link = $url; } - $link = &js_escape($link.(($url=~/\?/)?'&':'?').'inhibitmenu=yes'. - (($anchor ne '')?$anchor:'')); - if ($nomodal) { + $link = &js_escape($link.(($url=~/\?/)?'&':'?').'inhibitmenu=yes'.$anchor); + if ($allowed && !$env{'request.role.adv'} && !$isfolder && !$ispage && !$uploaded) { + if ((&LONCAPA::map::getparameter($orderidx,'parameter_hiddenresource'))[0]=~/^yes$/i) { + $nolink = 1; + } + } + if ($nolink) { + $line.='<img src="'.$icon.'" alt="" class="LC_icon" />'; + } elsif ($nomodal) { $line.='<a href="#" onclick="javascript:window.open('."'$link','syllabuspreview','height=400,width=500,scrollbars=1,resizable=1,menubar=0,location=1')".'; return false;" />'. '<img src="'.$icon.'" alt="" class="LC_icon" border="0" /></a>'; } else { @@ -4352,9 +4603,26 @@ $form_end; } $line.='</span></td><td'.$tdwidth.'>'; if (($url=~m{/adm/(coursedocs|supplemental)}) || (!$allowed && $url)) { - $line.='<a href="'.$url.'">'.$title.'</a>'; + if ($nolink) { + $line.=$title; + } else { + $line.='<a href="'.$url.'">'.$title.'</a>'; + } + if (!$allowed && $supplementalflag && $canedit && $isfolder) { + my $editicon = &Apache::loncommon::lonhttpdurl('/res/adm/pages').'/editmap.png'; + my $editurl = $url; + $editurl =~ s{^\Q/adm/supplemental?\E}{/adm/coursedocs?command=direct&forcesupplement=1&}; + $line .= ' '.'<a href="'.$editurl.'">'. + '<img src="'.$editicon.'" alt="'.&mt('Edit Content').'" title="'.&mt('Edit Content').'" />'. + '</a>'; + } + if ((($hiddenfolder) || ($hiddenres)) && (!$allowed) && ($supplementalflag)) { + $line.= ' <span class="LC_warning">('.&mt('hidden').')</span> '; + } } elsif ($url) { - if ($nomodal) { + if ($nolink) { + $line.=$title; + } elsif ($nomodal) { $line.='<a href="#" onclick="javascript:window.open('."'$link','syllabuspreview','height=400,width=500,scrollbars=1,resizable=1,menubar=0,location=1')".'; return false;" />'. $title.'</a>'; } else { @@ -4373,32 +4641,42 @@ $form_end; $line .= '</td>'; $rand_pick_text = ' ' if ($rand_pick_text eq ''); $rand_order_text = ' ' if ($rand_order_text eq ''); - if (($allowed) && ($folder!~/^supplemental/)) { - my %lt=&Apache::lonlocal::texthash( - 'hd' => 'Hidden', - 'ec' => 'URL hidden'); - my ($enctext,$hidtext); - if ((&LONCAPA::map::getparameter($orderidx,'parameter_encrypturl'))[0]=~/^yes$/i) { - $enctext = ' checked="checked"'; - if (($ishash) && (ref($filtersref->{'encrypturl'}) eq 'ARRAY')) { - push(@{$filtersref->{'encrypturl'}},$orderidx); - } + if ($uploaded && $url && !$isfolder && !$ispage) { + if (($plainurl ne '') && ($env{'request.role.adv'} || $allowed || !$hiddenres)) { + &Apache::lonnet::allowuploaded('/adm/coursedoc',$plainurl); } + } + if ($allowed) { + my %lt=&Apache::lonlocal::texthash( + 'hd' => 'Hidden', + 'ec' => 'URL hidden'); + my ($enctext,$hidtext,$formhidden,$formurlhidden); if ((&LONCAPA::map::getparameter($orderidx,'parameter_hiddenresource'))[0]=~/^yes$/i) { $hidtext = ' checked="checked"'; - if (($ishash) && (ref($filtersref->{'randomorder'}) eq 'ARRAY')) { + if (($ishash) && (ref($filtersref->{'hiddenresource'}) eq 'ARRAY')) { push(@{$filtersref->{'hiddenresource'}},$orderidx); } } - my $formhidden = 'edit_hiddenresource_'.$orderidx; - my $formurlhidden = 'edit_encrypturl_'.$orderidx; - $line.=(<<ENDPARMS); + $formhidden = 'edit_hiddenresource_'.$orderidx; + $line.=(<<ENDPARMS); <td class="LC_docs_entry_parameter"> <form action="/adm/coursedocs" method="post" name="$formhidden"> $form_param $form_common <label><input type="checkbox" name="hiddenresource_$orderidx" id="hiddenresource_$orderidx" onclick="checkForSubmit(this.form,'hiddenresource','settings');" $hidtext $disabled /> $lt{'hd'}</label> $form_end +ENDPARMS + if ($folder =~/^supplemental/) { + $line.= "\n <td>"; + } else { + if ((&LONCAPA::map::getparameter($orderidx,'parameter_encrypturl'))[0]=~/^yes$/i) { + $enctext = ' checked="checked"'; + if (($ishash) && (ref($filtersref->{'encrypturl'}) eq 'ARRAY')) { + push(@{$filtersref->{'encrypturl'}},$orderidx); + } + } + $formurlhidden = 'edit_encrypturl_'.$orderidx; + $line.=(<<ENDPARMS); <br /> <form action="/adm/coursedocs" method="post" name="$formurlhidden"> $form_param @@ -4409,6 +4687,7 @@ $form_end; <td class="LC_docs_entry_parameter">$rand_pick_text<br /> $rand_order_text</td> ENDPARMS + } } $line.=&Apache::loncommon::end_data_table_row(); return $line; @@ -4588,7 +4867,7 @@ sub untiehash { sub checkonthis { - my ($r,$url,$level,$title)=@_; + my ($r,$url,$level,$title,$checkstale)=@_; $url=&unescape($url); $alreadyseen{$url}=1; $r->rflush(); @@ -4603,10 +4882,22 @@ sub checkonthis { $r->print('<a href="'.$url.'" target="cat">'. ($title?$title:$url).'</a> '); if ($url=~/^\/res\//) { + my $updated; + if (($checkstale) && ($url !~ m{^/res/lib/templates/}) && + ($url !~ /\.\d+\.\w+$/)) { + $updated = &Apache::lonnet::remove_stale_resfile($url); + } my $result=&Apache::lonnet::repcopy( &Apache::lonnet::filelocation('',$url)); if ($result eq 'ok') { $r->print('<span class="LC_success">'.&mt('ok').'</span>'); + if ($updated) { + $r->print('<br />'); + for (my $i=0;$i<=$level*5;$i++) { + $r->print(' '); + } + $r->print('- '.&mt('Outdated copy removed')); + } $r->rflush(); &Apache::lonnet::countacc($url); $url=~/\.(\w+)$/; @@ -4640,7 +4931,7 @@ sub checkonthis { &Apache::lonnet::metadata($url,'dependencies'); foreach my $dep (split(/\,/,$dependencies)) { if (($dep=~/^\/res\//) && (!$alreadyseen{$dep})) { - &checkonthis($r,$dep,$level+1); + &checkonthis($r,$dep,$level+1,'',$checkstale); } } } elsif ($result eq 'unavailable') { @@ -4654,6 +4945,9 @@ sub checkonthis { } else { $r->print('<span class="LC_error">'.&mt('access denied').'</span>'); } + if (($updated) && ($result ne 'ok')) { + $r->print('<br />'.&mt('Outdated copy removed')); + } } } } @@ -4706,13 +5000,75 @@ sub list_symbs { $r->print(&endContentScreen()); } +sub short_urls { + my ($r,$canedit) = @_; + my $crstype = &Apache::loncommon::course_type(); + my $formname = 'shortenurl'; + $r->print(&Apache::loncommon::start_page('Display/Set Shortened URLs')); + $r->print(&Apache::lonhtmlcommon::breadcrumbs('Shortened URLs')); + $r->print(&startContentScreen('tools')); + my ($navmap,$errormsg) = + &Apache::loncourserespicker::get_navmap_object($crstype,'shorturls'); + my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + my (%maps,%resources,%titles); + if (!ref($navmap)) { + $r->print($errormsg. + &endContentScreen()); + return ''; + } else { + $r->print('<h4 class="LC_info">'.&mt('Tiny URLs for deep-linking into course').'</h4>'."\n"); + $r->rflush(); + my $readonly; + if ($canedit) { + my ($numnew,$errors) = &Apache::loncommon::get_requested_shorturls($cdom,$cnum,$navmap); + if ($numnew) { + $r->print('<p class="LC_info">'.&mt('Created [quant,_1,URL]',$numnew).'</p>'); + } + if ((ref($errors) eq 'ARRAY') && (@{$errors} > 0)) { + $r->print(&mt('The following errors occurred when processing your request to create shortened URLs:').'<br /><ul>'); + foreach my $error (@{$errors}) { + $r->print('<li>'.$error.'</li>'); + } + $r->print('</ul><br />'); + } + } else { + $readonly = 1; + } + my %currtiny = &Apache::lonnet::dump('tiny',$cdom,$cnum); + $r->print(&Apache::loncourserespicker::create_picker($navmap,'shorturls',$formname,$crstype,undef, + undef,undef,undef,undef,undef,\%currtiny,$readonly)); + } + $r->print(&endContentScreen()); +} -sub verifycontent { +sub contentverifyform { my ($r) = @_; my $crstype = &Apache::loncommon::course_type(); $r->print(&Apache::loncommon::start_page('Verify '.$crstype.' Content')); $r->print(&Apache::lonhtmlcommon::breadcrumbs('Verify '.$crstype.' Content')); $r->print(&startContentScreen('tools')); + $r->print('<h4 class="LC_info">'.&mt($crstype.' content verification').'</h4>'); + $r->print('<form method="post" action="/adm/coursedocs"><p>'. + &mt('Include a check if files copied from elsewhere are up to date (will increase verification time)?'). + ' <span class="LC_nobreak">'. + '<label><input type="radio" name="checkstale" value="0" checked="checked" />'. + &mt('No').'</label>'.(' 'x2). + '<label><input type="radio" name="checkstale" value="1" />'. + &mt('Yes').'</label></span></p><p>'. + '<input type="submit" value="'.&mt('Verify Content').' "/>'. + '<input type="hidden" value="1" name="tools" />'. + '<input type="hidden" value="1" name="verify" /></p></form>'); + $r->print(&endContentScreen()); + return; +} + +sub verifycontent { + my ($r,$checkstale) = @_; + my $crstype = &Apache::loncommon::course_type(); + $r->print(&Apache::loncommon::start_page('Verify '.$crstype.' Content')); + $r->print(&Apache::lonhtmlcommon::breadcrumbs('Verify '.$crstype.' Content')); + $r->print(&startContentScreen('tools')); $r->print('<h4 class="LC_info">'.&mt($crstype.' content verification').'</h4>'); $hashtied=0; undef %alreadyseen; @@ -4729,7 +5085,7 @@ sub verifycontent { } } if (($key=~/^src\_(.+)$/) && (!$alreadyseen{&unescape($hash{$key})})) { - &checkonthis($r,$hash{$key},0,$hash{'title_'.$1}); + &checkonthis($r,$hash{$key},0,$hash{'title_'.$1},$checkstale); } } &untiehash(); @@ -4737,7 +5093,6 @@ sub verifycontent { $r->print(&endContentScreen()); } - sub devalidateversioncache { my $src=shift; &Apache::lonnet::devalidate_cache_new('courseresversion',$env{'request.course.id'}.'_'. @@ -5057,13 +5412,17 @@ sub changewarning { if (!defined($message)) { $message='Changes will become active for your current session after [_1], or the next time you log in.'; } + my $windowname = 'loncapaclient'; + if ($env{'request.lti.login'}) { + $windowname .= 'lti'; + } $r->print("\n\n". '<script type="text/javascript">'."\n". '// <![CDATA['."\n". 'function reinit(tf) { tf.submit();'.$postexec.' }'."\n". '// ]]>'."\n". '</script>'."\n". -'<form name="reinitform" method="post" action="/adm/roles" target="loncapaclient">'. +'<form name="reinitform" method="post" action="/adm/roles" target="'.$windowname.'">'. '<input type="hidden" name="orgurl" value="'.$url. '" /><input type="hidden" name="selectrole" value="1" /><p class="LC_warning">'. &mt($message,' <input type="hidden" name="'. @@ -5184,17 +5543,20 @@ sub handler { $help{'Caching'} = &Apache::loncommon::help_open_topic('Caching'); my ($allowed,$canedit,$canview,$noendpage,$disabled); +# does this user have privileges to modify content. + if (&Apache::lonnet::allowed('mdc',$env{'request.course.id'})) { # URI is /adm/supplemental when viewing supplemental docs in non-edit mode. - unless ($r->uri eq '/adm/supplemental') { - # does this user have privileges to modify content. - if (&Apache::lonnet::allowed('mdc',$env{'request.course.id'})) { + unless ($r->uri eq '/adm/supplemental') { $allowed = 1; - $canedit = 1; - $canview = 1; - } elsif (&Apache::lonnet::allowed('cev',$env{'request.course.id'})) { + } + $canedit = 1; + $canview = 1; + } elsif (&Apache::lonnet::allowed('cev',$env{'request.course.id'})) { +# URI is /adm/supplemental when viewing supplemental docs in non-edit mode. + unless ($r->uri eq '/adm/supplemental') { $allowed = 1; - $canview = 1; } + $canview = 1; } unless ($canedit) { $disabled = ' disabled="disabled"'; @@ -5208,10 +5570,23 @@ sub handler { if ($allowed && $env{'form.verify'}) { &init_breadcrumbs('verify','Verify Content','Docs_Verify_Content'); - &verifycontent($r); + if (!$canedit) { + &verifycontent($r); + } elsif (($env{'form.checkstale'} ne '') && ($env{'form.checkstale'} =~ /^\d$/)) { + &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/coursedocs?tools=1&verify=1&checkstale=$env{'form.checkstale'}", + text=>'Results', + faq=>273, + bug=>'Instructor Interface'}); + &verifycontent($r,$env{'form.checkstale'}); + } else { + &contentverifyform($r); + } } elsif ($allowed && $env{'form.listsymbs'}) { &init_breadcrumbs('listsymbs','List Content IDs'); &list_symbs($r); + } elsif ($allowed && $env{'form.shorturls'}) { + &init_breadcrumbs('shorturls','Set/Display Shortened URLs','Docs_Short_URLs'); + &short_urls($r,$canedit); } elsif ($allowed && $env{'form.docslog'}) { &init_breadcrumbs('docslog','Show Log'); my $folder = $env{'form.folder'}; @@ -5275,6 +5650,8 @@ sub handler { $r->internal_redirect($redirect); return OK; } + } else { + $r->internal_redirect($redirect); } } } @@ -5284,7 +5661,7 @@ sub handler { # Get the parameters that may be needed # &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, - ['folderpath', + ['folderpath','title', 'forcesupplement','forcestandard', 'tools','symb','command','supppath']); @@ -5331,34 +5708,13 @@ sub handler { if ($env{'form.tools'}) { $toolsflag=1; } if ($env{'form.folderpath'} ne '') { - my @items = split(/\&/,$env{'form.folderpath'}); - my $badpath; - for (my $i=0; $i<@items; $i++) { - my $odd = $i%2; - if (($odd) && (!$supplementalflag) && ($items[$i] !~ /^[^:]*:(|\d+):(|1):(|1):(|1):(|1)$/)) { - $badpath = 1; - } elsif ((!$odd) && ($items[$i] !~ /^(default|supplemental)(|_\d+)$/)) { - $badpath = 1; - } - last if ($badpath); - } - if ($badpath) { - delete($env{'form.folderpath'}); - } + &Apache::loncommon::validate_folderpath($supplementalflag,$allowed,$coursenum,$coursedom); } + my $backto_supppath; if ($env{'form.supppath'} ne '') { - my @items = split(/\&/,$env{'form.supppath'}); - my $badpath; - for (my $i=0; $i<@items; $i++) { - my $odd = $i%2; - if ((!$odd) && ($items[$i] !~ /^supplemental(|_\d+)$/)) { - $badpath = 1; - } - last if ($badpath); - } - if ($badpath) { - delete($env{'form.supppath'}); + if ($supplementalflag && $allowed) { + $backto_supppath = &validate_supppath($coursenum,$coursedom); } } @@ -5380,10 +5736,10 @@ sub handler { &Apache::loncommon::symb_to_docspath($env{'form.symb'},\$navmap); &Apache::lonnet::appenv({'docs.exit.'.$env{'request.course.id'} => $env{'form.command'}.'_'.$env{'form.symb'}}); - } elsif ($env{'form.supppath'} ne '') { + } elsif (($env{'form.supppath'} ne '') && $supplementalflag && $allowed) { $env{'form.folderpath'}=$env{'form.supppath'}; &Apache::lonnet::appenv({'docs.exit.'.$env{'request.course.id'} => - $env{'form.command'}.'_'.$env{'form.supppath'}}); + $env{'form.command'}.'_'.$backto_supppath}); } } elsif ($env{'form.command'} eq 'editdocs') { $env{'form.folderpath'} = &default_folderpath($coursenum,$coursedom,\$navmap); @@ -5418,6 +5774,9 @@ sub handler { } else { undef($env{'form.folderpath'}); } + if ($env{'form.folderpath'} ne '') { + &Apache::loncommon::validate_folderpath($supplementalflag,$allowed,$coursenum,$coursedom); + } } # If we are not allowed to make changes, all we can see are supplemental docs @@ -5432,36 +5791,89 @@ sub handler { .'&'. $env{'form.folderpath'}; } -# If allowed and user's role is not advanced check folderpath is not hidden - if (($allowed) && (!$env{'request.role.adv'}) && - ($env{'form.folderpath'} ne '') && (!$supplementalflag)) { - my $folderurl; +# If allowed and user's role is not advanced check folderpath is not hidden + my $hidden_and_empty; + if (($allowed) && (!$env{'request.role.adv'}) && ($env{'form.folderpath'} ne '')) { + my ($folderurl,$foldername,$hiddenfolder); my @pathitems = split(/\&/,$env{'form.folderpath'}); my $folder = $pathitems[-2]; if ($folder eq '') { undef($env{'form.folderpath'}); } else { $folderurl = "uploaded/$coursedom/$coursenum/$folder"; - if ((split(/\:/,$pathitems[-1]))[4]) { + if ((split(/\:/,$pathitems[-1]))[5]) { $folderurl .= '.page'; } else { $folderurl .= '.sequence'; } - unless (ref($navmap)) { - $navmap = Apache::lonnavmaps::navmap->new(); - } - if (ref($navmap)) { - if (lc($navmap->get_mapparam(undef,$folderurl,"0.hiddenresource")) eq 'yes') { - my @resources = $navmap->retrieveResources($folderurl,$filterFunc,1,1); - unless (@resources) { - undef($env{'form.folderpath'}); + if ($supplementalflag) { + ($foldername,$hiddenfolder) = ($pathitems[-1] =~ /^([^:]*)::(|1):::$/); + $foldername = &HTML::Entities::decode(&unescape($foldername)); + my ($supplemental) = &Apache::loncommon::get_supplemental($coursenum,$coursedom); + if (ref($supplemental) eq 'HASH') { + my ($suppmap,$suppmapnum); + if ($folder eq 'supplemental') { + $suppmap = 'default'; + $suppmapnum = 0; + } elsif ($folder =~ /^supplemental_(\d+)$/) { + $suppmap = $1; + $suppmapnum = $suppmap; + } + if ($hiddenfolder) { + my $hascontent; + foreach my $key (reverse(sort(keys(%{$supplemental->{'ids'}})))) { + if ($key =~ m{^\Q/uploaded/$coursedom/$coursenum/supplemental/$suppmap/\E}) { + $hascontent = 1; + } elsif (ref($supplemental->{'ids'}->{$key}) eq 'ARRAY') { + foreach my $id (@{$supplemental->{'ids'}->{$key}}) { + if ($id =~ /^$suppmapnum\:/) { + $hascontent = 1; + last; + } + } + } + last if ($hascontent); + } + unless ($hascontent) { + if ($foldername ne '') { + $hidden_and_empty = $foldername; + } else { + $hidden_and_empty = $folder; + } + } + } + } + } else { + unless (ref($navmap)) { + $navmap = Apache::lonnavmaps::navmap->new(); + } + ($foldername,$hiddenfolder) = ($pathitems[-1] =~ /^([^:]*):|\d+:|1:(|1):|1:|1$/); + $foldername = &HTML::Entities::decode(&unescape($foldername)); + if (ref($navmap)) { + if ($hiddenfolder || + (lc($navmap->get_mapparam(undef,$folderurl,"0.hiddenresource")) eq 'yes')) { + my @resources = $navmap->retrieveResources($folderurl,$filterFunc,1,1); + unless (@resources) { + if ($foldername ne '') { + $hidden_and_empty = $foldername; + } else { + $hidden_and_empty = $folder; + } + } } } } + if ($hidden_and_empty ne '') { + splice(@pathitems,-2); + if (@pathitems) { + $env{'form.folderpath'} = join('&',@pathitems); + } else { + undef($env{'form.folderpath'}); + } + } } } - # If after all of this, we still don't have any paths, make them unless ($env{'form.folderpath'}) { if ($supplementalflag) { @@ -5536,7 +5948,7 @@ sub handler { my $tid = 1; my @tabids; if ($supplementalflag) { - @tabids = ('002','ee2','ff2'); + @tabids = ('002','dd2','ee2','ff2'); $tid = 2; } else { @tabids = ('aa1','bb1','cc1','ff1'); @@ -5546,7 +5958,7 @@ sub handler { } } my $tabidstr = join("','",@tabids); - %ltitools = &Apache::lonnet::get_domain_ltitools($coursedom); + %ltitools = &Apache::lonnet::get_domain_lti($coursedom,'consumer'); my $posslti = keys(%ltitools); my $hostname = $r->hostname(); $script .= &editing_js($udom,$uname,$supplementalflag,$coursedom,$coursenum,$posslti, @@ -5555,8 +5967,14 @@ sub handler { &inject_data_js(). &Apache::lonhtmlcommon::resize_scrollbox_js('docs',$tabidstr,$tid). &Apache::lonextresedit::extedit_javascript(\%ltitools); + my $onload = "javascript:resize_scrollbox('contentscroll','1','1');"; + if ($hidden_and_empty ne '') { + my $alert = &mt("Additional privileges required to edit empty and hidden folder: '[_1]'", + $hidden_and_empty); + $onload .= "javascript:alert('".&js_escape($alert)."');"; + } $addentries = { - onload => "javascript:resize_scrollbox('contentscroll','1','1');", + onload => $onload, }; } $script .= &paste_popup_js(); @@ -5578,8 +5996,15 @@ sub handler { &Apache::lonhtmlcommon::clear_breadcrumbs(); if ($showdoc) { - $r->print(&Apache::loncommon::start_page("$crstype documents",undef, - {'force_register' => $showdoc,})); + my $args; + if ($supplementalflag) { + my $title = &HTML::Entities::encode($env{'form.title'},'\'"<>&'); + my $brcrum = &Apache::lonhtmlcommon::docs_breadcrumbs(undef,$crstype,undef,$title,1); + $args = {'bread_crumbs' => $brcrum}; + } else { + $args = {'force_register' => $showdoc}; + } + $r->print(&Apache::loncommon::start_page("$crstype documents",undef,$args)); } elsif ($toolsflag) { my ($breadtext,$breadtitle); $breadtext = "$crstype Editor"; @@ -5597,6 +6022,12 @@ sub handler { $breadtitle) ); } elsif ($r->uri eq '/adm/supplemental') { + unless ($env{'request.role.adv'}) { + unless (&Apache::lonnet::has_unhidden_suppfiles($coursenum,$coursedom)) { + $r->internal_redirect('/adm/navmaps'); + return OK; + } + } my $brcrum = &Apache::lonhtmlcommon::docs_breadcrumbs(undef,$crstype); $r->print(&Apache::loncommon::start_page("Supplemental $crstype Content",undef, {'bread_crumbs' => $brcrum,})); @@ -5627,6 +6058,7 @@ sub handler { my %codebase = (); my ($upload_result,$upload_output,$uploadphase); if ($canedit) { + undef($suppchanges); if (($env{'form.uploaddoc.filename'}) && ($env{'form.cmd'}=~/^upload_(\w+)/)) { my $context = $1; @@ -5634,9 +6066,14 @@ sub handler { undef($hadchanges); $uploadphase = &process_file_upload(\$upload_output,$coursenum,$coursedom, \%allfiles,\%codebase,$context,$crstype); + undef($navmap); if ($hadchanges) { &mark_hash_old(); } + if ($suppchanges) { + &Apache::lonnet::update_supp_caches($coursedom,$coursenum); + undef($suppchanges); + } $r->print($upload_output); } elsif ($env{'form.phase'} eq 'upload_embedded') { # Process file upload - phase two - upload embedded objects @@ -5705,6 +6142,7 @@ sub handler { 'stpr' => 'Standard Problem', 'news' => 'New sub-directory', 'crpr' => 'Create Problem', + 'swit' => 'Switch Server', 'drbx' => 'Drop Box', 'scuf' => 'External Scores (handgrade, upload, clicker)', 'bull' => 'Discussion Board', @@ -5725,6 +6163,7 @@ sub handler { 'dire' => 'Directory:', 'cate' => 'Category:', 'tmpl' => 'Template:', + 'empd' => 'No resources found', 'comment' => 'Comment', 'parse' => 'Upload embedded images/multimedia files if HTML file', 'bb5' => 'Blackboard 5', @@ -5774,8 +6213,8 @@ sub handler { my $fileupload=(<<FIUP); $quotainfo $lt{'file'}:<br /> - <input type="file" name="uploaddoc" class="flUpload" size="40" $disabled /> - <input type="hidden" id="free_space" value="$free_space" /> + <input type="file" name="uploaddoc" class="LC_flUpload" size="40" $disabled /> + <input type="hidden" id="LC_free_space" value="$free_space" /> FIUP my $checkbox=(<<CHBO); @@ -5863,23 +6302,30 @@ FUFORM SEDFFORM my $importcrsresform; my ($numdirs,$pickfile) = - &Apache::loncommon::import_crsauthor_form('crsresimportform','coursepath','coursefile', + &Apache::loncommon::import_crsauthor_form('coursepath','coursefile', "resize_scrollbox('contentscroll','1','0');", undef,'res'); if ($pickfile) { $importcrsresform=(<<CRSFORM); - <a class="LC_menubuttons_link" href="javascript:toggleImportCrsres('res','$numdirs');"> + <a class="LC_menubuttons_link" href="javascript:toggleImportCrsres('res');"> $lt{'imcr'}</a>$help{'Course_Resources'} <form action="/adm/coursedocs" method="post" name="crsresimportform" onsubmit="return validImportCrsRes();"> <fieldset id="importcrsresform" style="display: none;"> <legend>$lt{'imcr'}</legend> + <div id="importcrsrescontent" style="display: none;"> <input type="hidden" name="active" value="bb" /> $pickfile <p> $lt{'title'}: <input type="textbox" name="crsrestitle" value="" $disabled /> </p> <input type="hidden" name="importdetail" value="" /> - <input type="submit" name="crsres" value="$lt{'impo'}" $disabled /> + <input type="submit" name="crsres" value="$lt{'impo'}" $disabled /><br /> + </div> + <div id="importcrsresempty" style="display: none;"> + <p> + $lt{'empd'} + </p> + </div> </fieldset> </form> CRSFORM @@ -5899,7 +6345,7 @@ CRSFORM { '<img class="LC_noBorder LC_middle" src="/res/adm/pages/sequence.png" alt="'.$lt{impm}.'" onclick="javascript:toggleMap(\'map\');" />' => $importpubform }, ); if ($pickfile) { - push(@importpubforma,{ '<img class="LC_noBorder LC_middle" src="/res/adm/pages/res.png" alt="'.$lt{imcr}.'" onclick="javascript:toggleImportCrsres(\'res\','."'$numdirs'".');"/>' => $importcrsresform}); + push(@importpubforma,{ '<img class="LC_noBorder LC_middle" src="/res/adm/pages/res.png" alt="'.$lt{imcr}.'" onclick="javascript:toggleImportCrsres(\'res\');" />' => $importcrsresform}); } $importpubform = &create_form_ul(&create_list_elements(@importpubforma)); my $extresourcesform = @@ -5971,9 +6417,13 @@ HIDDENFORM } my $postexec=''; if ($folder eq 'default') { + my $windowname = 'loncapaclient'; + if ($env{'request.lti.login'}) { + $windowname .= 'lti'; + } $r->print('<script type="text/javascript">'."\n" .'// <![CDATA['."\n" - .'this.window.name="loncapaclient";'."\n" + .'this.window.name="'.$windowname.'";'."\n" .'// ]]>'."\n" .'</script>'."\n" ); @@ -5986,7 +6436,7 @@ HIDDENFORM my $newnavform=(<<NNFORM); <form action="/adm/coursedocs" method="post" name="newnav"> - <input type="hidden" name="active" value="ee" /> + <input type="hidden" name="active" value="ff" /> $pathitem <input type="hidden" name="importdetail" value="$lt{'navc'}=/adm/navmaps" /> @@ -5996,7 +6446,7 @@ HIDDENFORM NNFORM my $newsmppageform=(<<NSPFORM); <form action="/adm/coursedocs" method="post" name="newsmppg"> - <input type="hidden" name="active" value="ee" /> + <input type="hidden" name="active" value="ff" /> $pathitem <input type="hidden" name="importdetail" value="" /> <a class="LC_menubuttons_link" href="javascript:makesmppage();"> $lt{'sipa'}</a> @@ -6006,7 +6456,7 @@ NSPFORM my $newsmpproblemform=(<<NSPROBFORM); <form action="/adm/coursedocs" method="post" name="newsmpproblem"> - <input type="hidden" name="active" value="cc" /> + <input type="hidden" name="active" value="dd" /> $pathitem <input type="hidden" name="importdetail" value="" /> <a class="LC_menubuttons_link" href="javascript:makesmpproblem();">$lt{'sipr'}</a> @@ -6017,7 +6467,7 @@ NSPROBFORM my $newdropboxform=(<<NDBFORM); <form action="/adm/coursedocs" method="post" name="newdropbox"> - <input type="hidden" name="active" value="cc" /> + <input type="hidden" name="active" value="dd" /> $pathitem <input type="hidden" name="importdetail" value="" /> <a class="LC_menubuttons_link" href="javascript:makedropbox();">$lt{'drbx'}</a> @@ -6027,7 +6477,7 @@ NDBFORM my $newexuploadform=(<<NEXUFORM); <form action="/adm/coursedocs" method="post" name="newexamupload"> - <input type="hidden" name="active" value="cc" /> + <input type="hidden" name="active" value="dd" /> $pathitem <input type="hidden" name="importdetail" value="" /> <a class="LC_menubuttons_link" href="javascript:makeexamupload();">$lt{'scuf'}</a> @@ -6037,7 +6487,7 @@ NEXUFORM my $newbulform=(<<NBFORM); <form action="/adm/coursedocs" method="post" name="newbul"> - <input type="hidden" name="active" value="dd" /> + <input type="hidden" name="active" value="ee" /> $pathitem <input type="hidden" name="importdetail" value="" /> <a class="LC_menubuttons_link" href="javascript:makebulboard();" >$lt{'bull'}</a> @@ -6047,7 +6497,7 @@ NBFORM my $newaboutmeform=(<<NAMFORM); <form action="/adm/coursedocs" method="post" name="newaboutme"> - <input type="hidden" name="active" value="dd" /> + <input type="hidden" name="active" value="ee" /> $pathitem <input type="hidden" name="importdetail" value="$plainname=/adm/$udom/$uname/aboutme" /> @@ -6058,7 +6508,7 @@ NAMFORM my $newaboutsomeoneform=(<<NASOFORM); <form action="/adm/coursedocs" method="post" name="newaboutsomeone"> - <input type="hidden" name="active" value="dd" /> + <input type="hidden" name="active" value="ee" /> $pathitem <input type="hidden" name="importdetail" value="" /> <a class="LC_menubuttons_link" href="javascript:makeabout();">$lt{'abou'}</a> @@ -6067,7 +6517,7 @@ NASOFORM my $newrosterform=(<<NROSTFORM); <form action="/adm/coursedocs" method="post" name="newroster"> - <input type="hidden" name="active" value="dd" /> + <input type="hidden" name="active" value="ee" /> $pathitem <input type="hidden" name="importdetail" value="$lt{'rost'}=/adm/viewclasslist" /> @@ -6088,7 +6538,7 @@ NROSTFORM } my $newwebpageform =(<<NWEBFORM); <form action="/adm/coursedocs" method="post" name="newwebpage"> - <input type="hidden" name="active" value="ee" /> + <input type="hidden" name="active" value="ff" /> $pathitem <input type="hidden" name="importdetail" value="$newwebpage" /> <a class="LC_menubuttons_link" href="javascript:makewebpage();">$lt{'webp'}</a> @@ -6097,133 +6547,62 @@ NROSTFORM NWEBFORM my @ids=&Apache::lonnet::current_machine_ids(); - my %select_menus; - my $numauthor = 0; - my $numcrsdirs = 0; - my $toppath = "/priv/$env{'user.domain'}/$env{'user.name'}"; + my $machines_str = "'".join("','",@ids)."'"; + my (%is_home,%toppath,$rolehomes); if ($env{'user.author'}) { - $numauthor ++; - $select_menus{'author'}->{'text'} = &Apache::lonnet::plaintext('au'); if (grep(/^\Q$env{'user.home'}\E$/,@ids)) { - my $is_home = 1; - my %subdirs; - &Apache::lonnet::recursedirs($is_home,'priv',$londocroot,$toppath,'',\%subdirs); - $select_menus{'author'}->{'default'} = '/'; - $select_menus{'author'}->{'select2'}->{'/'} = '/'; - my @ordered = ('/'); - foreach my $relpath (sort { lc($a) cmp lc($b) } (keys(%subdirs))) { - $select_menus{'author'}->{'select2'}->{$relpath} = $relpath; - push(@ordered,$relpath); - } - $select_menus{'author'}->{'order'} = \@ordered; - } else { - $select_menus{'author'}->{'select2'}->{'switch'} = &mt('Switch server required'); - $select_menus{'author'}->{'default'} = 'switch'; - $select_menus{'author'}->{'order'} = ['switch']; + $is_home{'author'} = 1; } + $rolehomes = '<input type="hidden" id="rolehome_author" name="rolehome_author" value="'.$env{'user.home'}.'" />'."\n"; } my %roleshash = &Apache::lonnet::get_my_roles($env{'user.name'},$env{'user.domain'},'userroles', ['active'],['ca','aa']); - my $crshome = $env{'course.'.$env{'request.course.id'}.'.home'}; my %by_roletype; if (keys(%roleshash)) { foreach my $entry (keys(%roleshash)) { my ($auname,$audom,$roletype) = split(/:/,$entry); my $key = $entry; $key =~ s/:/___/g; - $by_roletype{$roletype}{$auname.'___'.$audom} = 1; - $select_menus{$key}->{'text'} = &Apache::lonnet::plaintext($roletype)." ($audom/$auname)"; + my $author = $auname.'___'.$audom; + $by_roletype{$roletype}{$author} = 1; my $rolehome = &Apache::lonnet::homeserver($auname,$audom); - if (grep(/^\Q$rolehome\E$/,@ids)) { - my $is_home = 1; - my (%subdirs,@ordered); - my $toppath="/priv/$audom/$auname"; - &Apache::lonnet::recursedirs($is_home,'priv',$londocroot,$toppath,'',\%subdirs); - $select_menus{$key}->{'default'} = '/'; - $select_menus{$key}->{'select2'}->{'/'} = '/'; - my @ordered = ('/'); - foreach my $relpath (sort { lc($a) cmp lc($b) } (keys(%subdirs))) { - $select_menus{$key}->{'select2'}->{$relpath} = $relpath; - push(@ordered,$relpath); - } - $select_menus{$key}->{'order'} = \@ordered; - } else { - $select_menus{$key}->{'select2'}->{'switch'} = &mt('Switch server required'); - $select_menus{$key}->{'default'} = 'switch'; - $select_menus{$key}->{'order'} = ['switch']; - } - $numauthor ++; - } - } - my ($pickdir,$showtitle); - if ($numauthor) { - my @order; - my $defrole; - if ($env{'user.author'}) { - push(@order,'author'); - $defrole = 'author'; - } - if (keys(%by_roletype)) { - foreach my $possrole ('ca','aa') { - if (ref($by_roletype{$possrole}) eq 'HASH') { - foreach my $author (sort { lc($a) cmp lc($b) } (keys(%{$by_roletype{$possrole}}))) { - unless ($defrole) { - $defrole = $author; - } - push(@order,$author.'___'.$possrole); - } - } + $toppath{$author} = "/priv/$audom/$auname"; + if (grep(/^\Q$rolehome\E$/,@ids)) { + $is_home{$author} = 1; } + $rolehomes .= '<input type="hidden" id="rolehome_coauthor_'.$roletype.'_'.$audom.'/'.$auname.'" '. + 'name="rolehome_coauthor" value="'.$roletype.'='.$audom.'/'.$auname.'='.$rolehome.'" />'."\n"; } - $select_menus{'course'}->{'text'} = &mt('Course Resource'); - if (grep(/^\Q$crshome\E$/,@ids)) { - my $is_home = 1; - my %subdirs; - my $toppath="/priv/$coursedom/$coursenum"; - &Apache::lonnet::recursedirs($is_home,'priv',$londocroot,$toppath,'',\%subdirs); - $numcrsdirs = keys(%subdirs); - $select_menus{'course'}->{'default'} = '/'; - $select_menus{'course'}->{'select2'}->{'/'} = '/'; - my @ordered = ('/'); - foreach my $relpath (sort { lc($a) cmp lc($b) } (keys(%subdirs))) { - $select_menus{'course'}->{'select2'}->{$relpath} = $relpath; - push(@ordered,$relpath); - } - $select_menus{'course'}->{'order'} = \@ordered; - } else { - $select_menus{'course'}->{'select2'}->{'switch'} = &mt('Switch server required'); - $select_menus{'course'}->{'default'} = 'switch'; - $select_menus{'course'}->{'order'} = ['switch']; - } - push(@order,'course'); - $pickdir = $lt{'loca'}. - &Apache::loncommon::linked_select_forms('courseresform','<br />'.$lt{'dire'}, - $defrole,'authorrole','authorpath', - \%select_menus,\@order,'toggleCrsResTitle();', - '','priv').'<br />'; - $showtitle = 'none'; - } else { - my $is_home; - $showtitle = 'inline'; - if (grep(/^\Q$crshome\E$/,@ids)) { - $is_home = 1; - $pickdir .= '<input type="hidden" name="authorrole" value="course" />'; - my $toppath="/priv/$coursedom/$coursenum'}"; - my %subdirs; - &Apache::lonnet::recursedirs($is_home,'priv',$londocroot,$toppath,'',\%subdirs); - $numcrsdirs = keys(%subdirs); - if ($numcrsdirs) { - $pickdir .= &mt('Directory: ').'<select name="authorpath">'."\n". - '<option value="/">/</option>'."\n"; - foreach my $key (sort { lc($a) cmp lc($b) } (keys(%subdirs))) { - $pickdir .= '<option value="'.$key.'">'.$key.'</option>'."\n"; + } + my $crshome = $env{'course.'.$env{'request.course.id'}.'.home'}; + if (grep(/^\Q$crshome\E$/,@ids)) { + $is_home{'course'} = 1; + } + $rolehomes .= '<input type="hidden" id="rolehome_course" name="rolehome_course" value="'.$crshome.'" />'."\n"; + my $pickdir = $lt{'loca'}. + '<select name="authorrole" onchange="populateDirSelects(this.form,'."'authorrole','authorpath'".',1,1,0);">'."\n". + '<option value="" selected="selected">'.&mt('Select').'</option>'."\n"; + if ($env{'user.author'}) { + $pickdir .= '<option value="author">'.&Apache::lonnet::plaintext('au').'</option>'."\n"; + } + if (keys(%by_roletype)) { + foreach my $possrole ('ca','aa') { + if (ref($by_roletype{$possrole}) eq 'HASH') { + my $roletitle = &Apache::lonnet::plaintext($possrole); + foreach my $author (sort { lc($a) cmp lc($b) } (keys(%{$by_roletype{$possrole}}))) { + my ($none,$where,$auname,$audom) = split(/\//,$toppath{$author}); + $pickdir .= '<option value="'.$author.'___'.$possrole.'">'. + $roletitle." ($audom/$auname)</option>\n"; } - $pickdir .= '</select>'; - } else { - $pickdir .= '<input type="hidden" name="authorpath" value="/" />'."\n"; } } } + $pickdir .= '<option value="course">'.&mt('Course Resource').'</option>'."\n". + '</select><br />'."\n". + $lt{'dire'}. + '<select name="authorpath" onchange="toggleCrsResTitle();">'. + '<option value=""></option>'. + '</select><br />'."\n"; my %seltemplate_menus; my @files = &Apache::lonhomework::get_template_list('problem'); @@ -6266,14 +6645,15 @@ NWEBFORM my $templatepreview = '<a href="#" target="sample" onclick="javascript:getExample(600,420,\'yes\',true); return false;">'. '<span id="newresexample">'.&mt('Example').'<span></a>'; my $crsresform=(<<RESFORM); - <a class="LC_menubuttons_link" href="javascript:toggleCrsRes('res','$numauthor','$numcrsdirs');"> + <a class="LC_menubuttons_link" href="javascript:toggleCrsRes('res');"> $lt{'stpr'}</a>$help{'Course_Resource'} <form action="/adm/coursedocs" method="post" name="courseresform"> <fieldset id="crsresform" style="display:none;"> <legend>$lt{'stpr'}</legend> - <input type="hidden" name="active" value="ee" /> + <input type="hidden" name="active" value="bb" /> <p> $pickdir + <div id="newstdproblem" style="display:none;"> <span class="LC_nobreak">$lt{'news'}? <label><input type="radio" name="newsubdir" value="0" onclick="toggleNewsubdir(this.form);" checked="checked" $disabled />No</label> @@ -6284,7 +6664,7 @@ NWEBFORM $lt{'fnam'} <input type="text" size="20" name="newresourcename" autocomplete="off" $disabled /> <p> - <div id="newresource" style="display:$showtitle"> + <div id="newresource" style="display:none"> $lt{'addp'} <label><input type="radio" name="newresourceadd" value="0" checked="checked" onclick="toggleNewInCourse(this.form);" $disabled /> $lt{'no'}</label> @@ -6309,6 +6689,11 @@ NWEBFORM <input type="hidden" name="folderpath" value="$env{'form.folderpath'}" /> <input type="submit" name="newcrs" value="$lt{'crpr'}" $disabled /> </span> + </div> + <div id="stdprobswitch" style="display:none;"> + $rolehomes + <input type="button" name="switchfornewprob" value="$lt{'swit'}" onclick="switchForProb();" /> + </div> </fieldset> </form> @@ -6359,7 +6744,7 @@ NSYLFORM my $newgroupfileform=(<<NGFFORM); <form action="/adm/coursedocs" method="post" name="newgroupfiles"> - <input type="hidden" name="active" value="dd" /> + <input type="hidden" name="active" value="ee" /> $pathitem <input type="hidden" name="importdetail" value="$lt{'grpo'}=/adm/$coursedom/$coursenum/aboutme" /> @@ -6367,24 +6752,32 @@ NSYLFORM $help{'Group Portfolio'} </form> NGFFORM - @specialdocumentsforma=( + if ($container eq 'page') { + @specialdocumentsforma=( + {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/webpage.png" alt="'.$lt{webp}.'" onclick="javascript:makewebpage();" />'=>$newwebpageform}, + ); + } else { + @specialdocumentsforma=( {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/page.png" alt="'.$lt{newp}.'" onclick="javascript:makenewpage(document.newpage,\''.$pageseq.'\');" />'=>$newpageform}, {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/syllabus.png" alt="'.$lt{syll}.'" onclick="javascript:makenew(document.newsyl);" />'=>$newsylform}, {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/navigation.png" alt="'.$lt{navc}.'" onclick="javascript:makenew(document.newnav);" />'=>$newnavform}, {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/simple.png" alt="'.$lt{sipa}.'" onclick="javascript:makesmppage();" />'=>$newsmppageform}, {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/webpage.png" alt="'.$lt{webp}.'" onclick="javascript:makewebpage();" />'=>$newwebpageform}, - ); + ); + } $specialdocumentsform = &create_form_ul(&create_list_elements(@specialdocumentsforma)); - - my @importdoc = ( - {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/extres.png" alt="'.$lt{extr}.'" onclick="toggleUpload(\'ext\');" />'=>$extresourcesform} + my @external = ( + {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/extres.png" alt="'.$lt{extr}.'" onclick="toggleExternal(\'ext\');" />'=>$extresourcesform} ); if (keys(%ltitools)) { - push(@importdoc, - {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/exttool.png" alt="'.$lt{extt}.'" onclick="toggleUpload(\'tool\');" />'=>$exttoolform}, - ); + push(@external, + {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/exttool.png" alt="'.$lt{extt}.'" onclick="toggleExternal(\'tool\');" />'=>$exttoolform}, + ); } + my $externalform = &create_form_ul(&create_list_elements(@external)); + + my @importdoc = (); unless ($container eq 'page') { push(@importdoc, {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/ims.png" alt="'.$lt{imsf}.'" onclick="javascript:toggleUpload(\'ims\');" />'=>$imspform} @@ -6399,7 +6792,7 @@ NGFFORM {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/simpprob.png" alt="'.$lt{sipr}.'" onclick="javascript:makesmpproblem();" />'=>$newsmpproblemform}, {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/dropbox.png" alt="'.$lt{drbx}.'" onclick="javascript:makedropbox();" />'=>$newdropboxform}, {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/scoreupfrm.png" alt="'.$lt{scuf}.'" onclick="javascript:makeexamupload();" />'=>$newexuploadform}, - {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/simpprob.png" alt="'.$lt{stpr}.'" onclick="javascript:toggleCrsRes(\'res\','."'$numauthor','$numcrsdirs'".');" />'=>$crsresform}, + {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/simpprob.png" alt="'.$lt{stpr}.'" onclick="javascript:toggleCrsRes(\'res\');" />'=>$crsresform}, ); $gradingform = &create_form_ul(&create_list_elements(@gradingforma)); @@ -6415,12 +6808,13 @@ NGFFORM my %orderhash = ( 'aa' => ['Upload',$fileuploadform], 'bb' => ['Import',$importpubform], - 'cc' => ['Grading',$gradingform], + 'cc' => ['External',$externalform], + 'dd' => ['Grading',$gradingform], + 'ff' => ['Other',$specialdocumentsform], ); unless ($container eq 'page') { $orderhash{'00'} = ['Newfolder',$newfolderform]; - $orderhash{'dd'} = ['Collaboration',$communityform]; - $orderhash{'ee'} = ['Other',$specialdocumentsform]; + $orderhash{'ee'} = ['Collaboration',$communityform]; } $hadchanges=0; @@ -6433,8 +6827,10 @@ unless ($container eq 'page') { $r->print('<p><span class="LC_error">'.$error.'</span></p>'); } if ($hadchanges) { - &mark_hash_old(); - } + unless (&is_hash_old()) { + &mark_hash_old(); + } + } &changewarning($r,''); } @@ -6446,7 +6842,7 @@ unless ($container eq 'page') { unless ($supplementalflag) { $folder='supplemental'; } - if ($folder =~ /^supplemental$/ && + if (($folder eq 'supplemental') && (($env{'form.folderpath'} =~ /^default\&/) || ($env{'form.folderpath'} eq ''))) { $env{'form.folderpath'} = &supplemental_base(); } elsif ($allowed) { @@ -6554,15 +6950,15 @@ my @specialdocs = ( {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/webpage.png" alt="'.$lt{webp}.'" onclick="javascript:makewebpage('."'supp'".');" />'=>$supwebpageform}, ); -my @supimportdoc = ( - {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/extres.png" alt="'.$lt{extr}.'" onclick="javascript:toggleUpload(\'suppext\')" />' - =>$supextform}); + my @supexternal = ( + {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/extres.png" alt="'.$lt{extr}.'" onclick="javascript:toggleExternal(\'suppext\')" />' + =>$supextform}); if (keys(%ltitools)) { - push(@supimportdoc, - {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/exttool.png" alt="'.$lt{extt}.'" onclick="javascript:toggleUpload(\'supptool\')" />' + push(@supexternal, + {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/exttool.png" alt="'.$lt{extt}.'" onclick="javascript:toggleExternal(\'supptool\')" />' =>$supexttoolform}); } - push(@supimportdoc, + my @supimportdoc = ( {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/pdfupload.png" alt="'.$lt{upl}.'" onclick="javascript:toggleUpload(\'suppdoc\');" />' =>$supupdocform}, ); @@ -6570,33 +6966,27 @@ my @supimportdoc = ( $supupdocform = &create_form_ul(&create_list_elements(@supimportdoc)); my %suporderhash = ( '00' => ['Supnewfolder', $supnewfolderform], - 'ee' => ['Upload',$supupdocform], + 'dd' => ['Upload',$supupdocform], + 'ee' => ['External',&create_form_ul(&create_list_elements(@supexternal))], 'ff' => ['Other',&create_form_ul(&create_list_elements(@specialdocs))] ); if ($supplementalflag) { - my $error = &editor($r,$coursenum,$coursedom,$folder,$allowed,'',$crstype, - $supplementalflag,\%suporderhash,$iconpath,$pathitem, - \%ltitools,$canedit,$hostname); - if ($error) { - $r->print('<p><span class="LC_error">'.$error.'</span></p>'); - } else { - if ($suppchanges) { - my %servers = &Apache::lonnet::internet_dom_servers($coursedom); - my @ids=&Apache::lonnet::current_machine_ids(); - foreach my $server (keys(%servers)) { - next if (grep(/^\Q$server\E$/,@ids)); - my $hashid=$coursenum.':'.$coursedom; - my $cachekey = &escape('suppcount').':'.&escape($hashid); - &Apache::lonnet::remote_devalidate_cache($server,[$cachekey]); - } - &Apache::lonnet::get_numsuppfiles($coursenum,$coursedom,1); - undef($suppchanges); - } - } + $suppchanges = 0; + my $error = &editor($r,$coursenum,$coursedom,$folder,$allowed,'',$crstype, + $supplementalflag,\%suporderhash,$iconpath,$pathitem, + \%ltitools,$canedit,$hostname); + if ($error) { + $r->print('<p><span class="LC_error">'.$error.'</span></p>'); + } + if ($suppchanges) { + &Apache::lonnet::update_supp_caches($coursedom,$coursenum); + undef($suppchanges); + } } } elsif ($supplementalflag) { my $error = &editor($r,$coursenum,$coursedom,$folder,$allowed,'',$crstype, - $supplementalflag,'',$iconpath,$pathitem,'','',$hostname); + $supplementalflag,'',$iconpath,$pathitem,'',$canedit, + $hostname); if ($error) { $r->print('<p><span class="LC_error">'.$error.'</span></p>'); } @@ -6760,6 +7150,10 @@ sub remove_archive { if ($url eq $env{'form.archiveurl'}) { if (&handle_edit_cmd($docuname,$docudom)) { ($errtext,$fatal) = &storemap($docuname,$docudom,$map,1); + if ($suppchanges) { + &Apache::lonnet::update_supp_caches($docudom,$docuname); + undef($suppchanges); + } if ($fatal) { if ($container eq 'page') { $delwarning = &mt('An error occurred updating the contents of the current page.'); @@ -6798,6 +7192,7 @@ sub generate_admin_menu { 'vc' => 'Verify Content', 'cv' => 'Check/Set Resource Versions', 'ls' => 'List Resource Identifiers', + 'ct' => 'Display/Set Shortened URLs for Deep-linking', 'imse' => 'Export contents to IMS Archive', 'dcd' => "Copy $crstype Content to Authoring Space", ); @@ -6848,6 +7243,13 @@ sub generate_admin_menu { icon => 'symbs.png', linktitle => "List the unique identifier used for each resource instance in your $lc_crstype" }, + { linktext => $lt{'ct'}, + url => "javascript:injectData(document.courseverify,'dummy','shorturls','$lt{'ct'}')", + permission => 'F', + help => 'Docs_Short_URLs', + icon => 'shorturls.png', + linktitle => "Set shortened URLs for a resource or folder in your $lc_crstype for use in deep-linking" + }, ] }); if ($canedit) { @@ -7026,6 +7428,8 @@ sub editing_js { tinc => 'Title in course', sunm => 'Sub-directory name', edri => 'Editing rights unavailable for your current role.', + sele => 'Select', + swit => 'Switch server required', ); &js_escape(\%js_lt); my $crstype = &Apache::loncommon::course_type(); @@ -7037,7 +7441,9 @@ sub editing_js { my $backtourl; my $toplevelmain = &escape(&default_folderpath($coursenum,$coursedom,$navmapref)); my $toplevelsupp = &supplemental_base(); - + my $showfile_js = &Apache::loncommon::show_crsfiles_js(); + my @ids=&Apache::lonnet::current_machine_ids(); + my $machines_str = "'".join("','",@ids)."'"; if ($env{'docs.exit.'.$env{'request.course.id'}} =~ /^direct_(.+)$/) { my $caller = $1; if ($caller =~ /^supplemental/) { @@ -7056,19 +7462,31 @@ sub editing_js { } else { $url = $res; } - $backtourl = &HTML::Entities::encode(&Apache::lonnet::clutter($url),'<>&"').'?symb='. - &HTML::Entities::encode($caller,'<>&"'); + $backtourl = &HTML::Entities::encode(&Apache::lonnet::clutter($url),'<>&"'); + if ($backtourl =~ m{^\Q/uploaded/$coursedom/$coursenum/\Edefault_\d+\.sequence$}) { + $backtourl .= '?navmap=1'; + } else { + $backtourl .= '?symb='. + &HTML::Entities::encode($caller,'<>&"'); + } if ($backtourl =~ m{^\Q/public/$coursedom/$coursenum/syllabus\E}) { if (($ENV{'SERVER_PORT'} == 443) && ($env{'course.'.$env{'request.course.id'}.'.externalsyllabus'} =~ m{^http://})) { - if ($hostname ne '') { - $backtourl = 'http://'.$hostname.$backtourl; + unless ((&Apache::lonnet::uses_sts()) || (&Apache::lonnet::waf_allssl($hostname))) { + if ($hostname ne '') { + $backtourl = 'http://'.$hostname.$backtourl; + } + $backtourl .= (($backtourl =~ /\?/) ? '&':'?').'usehttp=1'; } - $backtourl .= (($backtourl =~ /\?/) ? '&':'?').'usehttp=1'; } } elsif ($backtourl =~ m{^/adm/wrapper/ext/(?!https:)}) { if (($ENV{'SERVER_PORT'} == 443) && ($hostname ne '')) { - $backtourl = 'http://'.$hostname.$backtourl; + unless ((&Apache::lonnet::uses_sts()) || (&Apache::lonnet::waf_allssl($hostname))) { + if ($hostname ne '') { + $backtourl = 'http://'.$hostname.$backtourl; + } + $backtourl .= (($backtourl =~ /\?/) ? '&':'?').'usehttp=1'; + } } } if ($anchor ne '') { @@ -7082,32 +7500,39 @@ sub editing_js { } elsif ($env{'docs.exit.'.$env{'request.course.id'}} eq '/adm/menu') { $backtourl = '/adm/menu'; } elsif ($supplementalflag) { - $backtourl = '/adm/supplemental'; + if (($env{'request.role.adv'}) || + (&Apache::lonnet::has_unhidden_suppfiles($coursenum,$coursedom))) { + $backtourl = '/adm/supplemental'; + } else { + $backtourl = '/adm/navmaps'; + } } else { $backtourl = '/adm/navmaps'; } - my $fieldsets = "'ext','doc'"; - if ($posslti) { - $fieldsets .= ",'tool'"; - } + my $fieldsets = "'doc'"; unless ($main_container_page) { $fieldsets .=",'ims'"; } + my $extfieldsets = "'ext'"; + if ($posslti) { + $extfieldsets .= ",'tool'"; + } if ($supplementalflag) { - $fieldsets = "'suppext','suppdoc'"; + $fieldsets = "'suppdoc'"; + $extfieldsets = "'suppext'"; if ($posslti) { - $fieldsets .= ",'supptool'"; + $extfieldsets .= ",'supptool'"; } } - + my $jsmakefunctions; if ($canedit) { $jsmakefunctions = <<ENDNEWSCRIPT; function makenewfolder(targetform,folderseq) { var foldername=prompt('$js_lt{"p_mnf"}','$js_lt{"t_mnf"}'); if (foldername) { - targetform.importdetail.value=escape(foldername)+"="+folderseq; + targetform.importdetail.value=encodeURIComponent(foldername)+"="+folderseq; targetform.submit(); } } @@ -7115,7 +7540,7 @@ function makenewfolder(targetform,folder function makenewpage(targetform,folderseq) { var pagename=prompt('$js_lt{"p_mnp"}','$js_lt{"t_mnp"}'); if (pagename) { - targetform.importdetail.value=escape(pagename)+"="+folderseq; + targetform.importdetail.value=encodeURIComponent(pagename)+"="+folderseq; targetform.submit(); } } @@ -7124,7 +7549,7 @@ function makeexamupload() { var title=prompt('$js_lt{"p_mxu"}'); if (title) { this.document.forms.newexamupload.importdetail.value= - escape(title)+'=/res/lib/templates/examupload.problem'; + encodeURIComponent(title)+'=/res/lib/templates/examupload.problem'; this.document.forms.newexamupload.submit(); } } @@ -7133,7 +7558,7 @@ function makesmppage() { var title=prompt('$js_lt{"p_msp"}'); if (title) { this.document.forms.newsmppg.importdetail.value= - escape(title)+'=/adm/$udom/$uname/new/smppg'; + encodeURIComponent(title)+'=/adm/$udom/$uname/new/smppg'; this.document.forms.newsmppg.submit(); } } @@ -7148,7 +7573,7 @@ function makewebpage(type) { } if (title) { var webpage = formname.importdetail.value; - formname.importdetail.value = escape(title)+'='+webpage; + formname.importdetail.value = encodeURIComponent(title)+'='+webpage; formname.submit(); } } @@ -7157,7 +7582,7 @@ function makesmpproblem() { var title=prompt('$js_lt{"p_msb"}'); if (title) { this.document.forms.newsmpproblem.importdetail.value= - escape(title)+'=/res/lib/templates/simpleproblem.problem'; + encodeURIComponent(title)+'=/res/lib/templates/simpleproblem.problem'; this.document.forms.newsmpproblem.submit(); } } @@ -7166,7 +7591,7 @@ function makedropbox() { var title=prompt('$js_lt{"p_mdb"}'); if (title) { this.document.forms.newdropbox.importdetail.value= - escape(title)+'=/res/lib/templates/DropBox.problem'; + encodeURIComponent(title)+'=/res/lib/templates/DropBox.problem'; this.document.forms.newdropbox.submit(); } } @@ -7175,7 +7600,7 @@ function makebulboard() { var title=prompt('$js_lt{"p_mbb"}'); if (title) { this.document.forms.newbul.importdetail.value= - escape(title)+'=/adm/$udom/$uname/new/bulletinboard'; + encodeURIComponent(title)+'=/adm/$udom/$uname/new/bulletinboard'; this.document.forms.newbul.submit(); } } @@ -7321,16 +7746,32 @@ function toggleUpload(caller) { } } document.getElementById('upload'+blocks[i]+'form').style.display=disp; + } + resize_scrollbox('contentscroll','1','1'); + return; +} + +function toggleExternal(caller) { + var blocks = Array($extfieldsets); + for (var i=0; i<blocks.length; i++) { + var disp = 'none'; + if (caller == blocks[i]) { + var curr = document.getElementById('external'+caller+'form').style.display; + if (curr == 'none') { + disp='block'; + } + } + document.getElementById('external'+blocks[i]+'form').style.display=disp; if ((caller == 'tool') || (caller == 'supptool')) { if (disp == 'block') { - if (document.getElementById('LC_exttoolid')) { - var toolselector = document.getElementById('LC_exttoolid'); + if (document.getElementById('LC_exttoolid')) { + var toolselector = document.getElementById('LC_exttoolid'); var suppflag = 0; if (caller == 'supptool') { suppflag = 1; } currForm = document.getElementById('new'+caller); - updateExttool(toolselector,currForm,suppflag); + updateExttool(toolselector,currForm,suppflag); } } } @@ -7354,27 +7795,21 @@ function toggleMap(caller) { return; } -function toggleCrsRes(caller,numauthorrole,numcrsdirs) { +function toggleCrsRes(caller) { var disp = 'none'; if (document.getElementById('crsresform')) { if (caller == 'res') { - var curr = document.getElementById('crsresform').style.display; + var form = document.getElementById('crsresform'); + var curr = form.style.display; if (curr == 'none') { disp='block'; - numauthor = parseInt(numauthorrole); - if (numauthor > 0) { - document.courseresform.authorrole.selectedIndex = 0; - select1priv_changed(); - document.courseresform.authorpath.selectedIndex = 0; - document.courseresform.newresourceadd.selectedIndex = 0; - toggleNewInCourse(document.courseresform); - if (document.getElementById('newresource')) { - document.getElementById('newresource').style.display = 'none'; - } - } else { - if (numcrsdirs) { - document.courseresform.authorpath.selectedIndex = 0; - } + document.courseresform.authorrole.selectedIndex = 0; + document.courseresform.authorpath.selectedIndex = 0; + document.courseresform.newresourceadd.selectedIndex = 0; + populateDirSelects(form,'authorrole','authorpath',1,0,0); + toggleNewInCourse(document.courseresform); + if (document.getElementById('newresource')) { + document.getElementById('newresource').style.display = 'none'; } if (document.courseresform.newresusetemp.length) { document.courseresform.newresusetemp[0].checked = true; @@ -7428,14 +7863,28 @@ function toggleNewsubdir(form) { function toggleCrsResTitle() { if (document.getElementById('newresource')) { - if (document.courseresform.authorrole.options[document.courseresform.authorrole.selectedIndex].value == 'course') { + var selloc = document.courseresform.authorrole.options[document.courseresform.authorrole.selectedIndex].value; + if (selloc == 'course') { document.getElementById('newresource').style.display = 'inline'; document.courseresform.newresourceadd[0].checked = true; toggleNewInCourse(document.courseresform); } else { document.getElementById('newresource').style.display = 'none'; } - } + } + if (document.getElementById('newstdproblem')) { + if (document.courseresform.authorpath.options[document.courseresform.authorpath.selectedIndex].value == 'switch') { + document.getElementById('newstdproblem').style.display = 'none'; + if (document.getElementById('stdprobswitch')) { + document.getElementById('stdprobswitch').style.display = 'block'; + } + } else { + document.getElementById('newstdproblem').style.display = 'block'; + if (document.getElementById('stdprobswitch')) { + document.getElementById('stdprobswitch').style.display = 'none'; + } + } + } } function toggleNewInCourse(form) { @@ -7515,16 +7964,28 @@ function getExample(width,height,scrolli } } -function toggleImportCrsres(caller,dircount) { +function toggleImportCrsres(caller) { var disp = 'none'; if (document.getElementById('importcrsresform')) { if (caller == 'res') { - var numdirs = parseInt(dircount); var curr = document.getElementById('importcrsresform').style.display; if (curr == 'none') { disp='block'; - if (numdirs > 1) { - select1res_changed(); + populateCrsSelects(document.crsresimportform,'coursepath','coursefile',1,'',1,0,1,1,0); + if ((document.getElementById('importcrsrescontent')) && + (document.getElementById('importcrsresempty'))) { + var selelem = document.crsresimportform.elements['coursepath']; + var numdirs = 0; + if (selelem.options.length) { + numdirs = selelem.options.length - 1; + } + if (numdirs) { + document.getElementById('importcrsrescontent').style.display='block'; + document.getElementById('importcrsresempty').style.display='none'; + } else { + document.getElementById('importcrsrescontent').style.display='none'; + document.getElementById('importcrsresempty').style.display='block'; + } } } } @@ -7534,6 +7995,152 @@ function toggleImportCrsres(caller,dirco return; } +$showfile_js + +function populateDirSelects(form,locsel,dirsel,setdir,recurse,nonemptydir) { + var location = form.elements[locsel].options[form.elements[locsel].selectedIndex].value; + if ((setdir) && (dirsel != null) && (dirsel != 'undefined') && (dirsel != '')) { + var selelem = form.elements[dirsel]; + var i, numfiles = selelem.options.length -1; + if (numfiles >=0) { + for (i = numfiles; i >= 0; i--) { + selelem.remove(i); + } + } + if ((location == '') || (location == null) || (location == 'undefined')) { + if (selelem.options.length == 0) { + selelem.options[selelem.options.length] = new Option('',''); + selelem.selectedIndex = 0; + } + if (document.getElementById('newstdproblem')) { + document.getElementById('newstdproblem').style.display = 'none'; + } + return; + } + var machineIds = new Array($machines_str); + var athome = 0; + var role = location; + if ((location == 'author') || (location == 'course')) { + if (document.getElementById('rolehome_'+location)) { + var currhome = document.getElementById('rolehome_'+location).value; + if ((currhome != '') && (currhome != null) && (currhome != 'undefined')) { + if (machineIds.includes(currhome)) { + athome = 1; + } + } + } + } else { + const roleinfo = location.split('___'); + role = encodeURIComponent(roleinfo[0]+'./'+roleinfo[1]); + if (document.getElementById('rolehome_coauthor_'+roleinfo[1]+'_'+roleinfo[0])) { + var currhome = document.getElementById('rolehome_coauthor_'+roleinfo[1]+'_'+roleinfo[0]).value; + if ((currhome != '') && (currhome != null) && (currhome != 'undefined')) { + if (machineIds.includes(currhome)) { + athome = 1; + } + } + } + } + if (athome) { + if (document.getElementById('stdprobswitch')) { + document.getElementById('stdprobswitch').style.display = 'none'; + } + if (document.getElementById('newstdproblem')) { + document.getElementById('newstdproblem').style.display = 'none'; + } + var http = new XMLHttpRequest(); + var url = "/adm/courseauthor"; + var params = "role="+role+"&rec="+recurse+"&nonempty="+nonemptydir+"&addtop=1"; + http.open("POST", url, true); + http.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); + http.onreadystatechange = function() { + if (http.readyState == 4 && http.status == 200) { + var data = JSON.parse(http.responseText); + if (Array.isArray(data.dirs)) { + var len = data.dirs.length; + if (len) { + if (len > 1) { + selelem.options[selelem.options.length] = new Option('$js_lt{sele}',''); + } + } + if (len) { + var j; + for (j = 0; j < len; j++) { + selelem.options[selelem.options.length] = new Option(data.dirs[j],data.dirs[j]); + } + selelem.selectedIndex = 0; + if (len == 1) { + toggleCrsResTitle(); + } + } + } + } + } + http.send(params); + } else { + selelem.options[selelem.options.length] = new Option('$js_lt{swit}','switch'); + selelem.selectedIndex = 0; + if (document.getElementById('stdprobswitch')) { + document.getElementById('stdprobswitch').style.display = 'block'; + } + if (document.getElementById('newstdproblem')) { + document.getElementById('newstdproblem').style.display = 'none'; + } + } + } + return; +} + +function switchForProb() { + if (document.courseresform.authorpath.options[document.courseresform.authorpath.selectedIndex].value == 'switch') { + var url = '/adm/switchserver?otherserver='; + var newhostid = ''; + var role = ''; + var selloc = document.courseresform.authorrole.options[document.courseresform.authorrole.selectedIndex].value; + if (selloc == 'author') { + newhostid = document.courseresform.rolehome_author.value; + role = "au./&js_escape($env{'user.domain'})/"; + } else if (selloc == 'course') { + newhostid = document.courseresform.rolehome_course.value; + role = "&js_escape($env{'request.role'})"; + } else { + var items = new Array(); + items = selloc.split('___'); + var len = document.courseresform.rolehome_coauthor.length; + if (null == len) { + var currval = document.courseresform.rolehome_coauthor.value; + if (null != currval) { + var info = new Array(); + info = currval.split('='); + newhostid = info[2]; + role = info[0]+'./'+info[1]; + } + } else { + for (var i=0; i<len; i++) { + var currval = document.courseresform.rolehome_coauthor[i].value; + if (null != currval) { + var info = new Array(); + info = currval.split('='); + if ((info[1] == items[1]+'/'+items[0]) && (info[0] == items[2])) { + newhostid = info[2]; + role = info[0]+'./'+info[1]; + break; + } + } + } + } + } + if (newhostid != '') { + url += newhostid; + if (role != '') { + url += '&role='+role; + } + document.location.href = url; + } + } + return; +} + function makeims(imsform) { if ((imsform.uploaddoc.value == '') || (!imsform.uploaddoc.value)) { alert("$js_lt{'imsfile'}"); @@ -7887,6 +8494,7 @@ function showPage(current, pageId, nav, current.className = 'right'; } activeTab = ''; + toggleExternal(); toggleUpload(); toggleMap(); toggleCrsRes(); @@ -7899,6 +8507,7 @@ function showPage(current, pageId, nav, currentData = document.getElementById(pageId); currentData.style.display = 'block'; activeTab = pageId; + toggleExternal(); toggleUpload(); toggleMap(); toggleCrsRes(); @@ -8281,7 +8890,7 @@ function validImportCrsRes() { url += fname; } var title = document.crsresimportform.crsrestitle.value; - document.crsresimportform.importdetail.value=escape(title)+'='+escape(url); + document.crsresimportform.importdetail.value=encodeURIComponent(title)+'='+encodeURIComponent(url); return true; } @@ -8432,7 +9041,7 @@ sub makenewproblem { if ($env{'form.newsubdir'}) { if ($env{'form.newsubdirname'} ne '') { $newsubdir = $env{'form.newsubdirname'}; - } + } } if ($env{'form.newresourcename'}) { $filename = $env{'form.newresourcename'}; @@ -8515,61 +9124,34 @@ END <subject></subject> <title></title> END - close($fh); - } - if ((-e $sourcerights) && (-e "$sourcerights.meta")) { - if (!-e "$docroot/res/$coursedom") { - mkdir("$docroot/res/$coursedom",0755); - } - if (!-e "$docroot/res/$coursedom/$coursenum") { - mkdir("$docroot/res/$coursedom/$coursenum",0755); - } - if ((-e "$docroot/res/$coursedom/$coursenum") && (!-e $targetrights)) { - my $nokeyref = &Apache::lonpublisher::getnokey($r->dir_config('lonIncludes')); - my $output = &Apache::lonpublisher::batchpublish($r,$sourcerights,$targetrights,$nokeyref,1); - } + close($fh); } } - if ($env{'form.newresourceadd'}) { - my $template = $env{'form.template'}; - my $source = $docroot.$redirect; - my $target = $redirect; - $target =~ s{^/priv/}{/res/}; - $target = $docroot.$target; - if (!-e $source) { - my $copyfrom; - if ($template) { - my %templates; - my @files = &Apache::lonhomework::get_template_list('problem'); - foreach my $poss (@files) { - if (ref($poss) eq 'ARRAY') { - if ($template eq $poss->[0]) { - $templates{$template} = 1; - last; - } - } - } - if ($templates{$template}) { - $copyfrom = $template; - } - } - unless ($copyfrom) { - $copyfrom = $r->dir_config('lonIncludes').'/templates/blank.problem'; - } - &File::Copy::copy($copyfrom,$source); + if ((-e $sourcerights) && (-e "$sourcerights.meta")) { + if (!-e "$docroot/res/$coursedom") { + mkdir("$docroot/res/$coursedom",0755); } - if (!-e "$source.meta") { - my $cid = $coursedom.'_'.$coursenum; - my $now = time; - if (open(my $fh,">$source.meta")) { - my $author=$env{'environment.firstname'}.' '. - $env{'environment.middlename'}.' '. - $env{'environment.lastname'}.' '. - $env{'environment.generation'}; - $author =~ s/\s+$//; - my $title = $env{'form.newresourcetitle'}; - $title =~ s/^\s+|\s+$//g; - print $fh <<END; + if (!-e "$docroot/res/$coursedom/$coursenum") { + mkdir("$docroot/res/$coursedom/$coursenum",0755); + } + if ((-e "$docroot/res/$coursedom/$coursenum") && (!-e $targetrights)) { + my $nokeyref = &Apache::lonpublisher::getnokey($r->dir_config('lonIncludes')); + my $output = &Apache::lonpublisher::batchpublish($r,$sourcerights,$targetrights,$nokeyref,1); + } + } + my $source = $docroot.$redirect; + if (!-e "$source.meta") { + my $cid = $coursedom.'_'.$coursenum; + my $now = time; + if (open(my $fh,">$source.meta")) { + my $author=$env{'environment.firstname'}.' '. + $env{'environment.middlename'}.' '. + $env{'environment.lastname'}.' '. + $env{'environment.generation'}; + $author =~ s/\s+$//; + my $title = $env{'form.newresourcetitle'}; + $title =~ s/^\s+|\s+$//g; + print $fh <<END; <abstract></abstract> <author>$author</author> @@ -8595,8 +9177,7 @@ END <subject></subject> <title>$title</title> END - close($fh); - } + close($fh); } } } @@ -8624,7 +9205,7 @@ END } sub finishnewprob { - my ($url,$path,$subdir,$newsubdir,$filename) = @_; + my ($url,$path,$subdir,$newsubdir,$filename,$context) = @_; unless (-d $path) { unless (mkdir($path,02770)) { return; @@ -8667,6 +9248,31 @@ sub finishnewprob { $redirect = "$url/$filename"; } } + if ((!-e $dest) && ($context ne 'upload')) { + my $template = $env{'form.template'}; + my $copyfrom; + if ($template ne '') { + my %templates; + my @files = &Apache::lonhomework::get_template_list('problem'); + foreach my $poss (@files) { + if (ref($poss) eq 'ARRAY') { + if ($template eq $poss->[0]) { + $templates{$template} = 1; + last; + } + } + } + if ($templates{$template}) { + $copyfrom = $template; + } + } + if ($filename =~ /\.problem$/) { + unless ($copyfrom) { + $copyfrom = $Apache::lonnet::perlvar{'lonIncludes'}.'/templates/blank.problem'; + } + &File::Copy::copy($copyfrom,$dest); + } + } return $redirect; } @@ -8778,7 +9384,9 @@ check on this Verify Content -=item devalidateversioncache() & checkversions() +=item devalidateversioncache() + +=item checkversions() Check Versions