--- loncom/publisher/loncfile.pm 2015/01/19 15:36:11 1.123 +++ loncom/publisher/loncfile.pm 2023/07/14 14:32:57 1.126 @@ -9,7 +9,7 @@ # and displays a page showing the results of the action. # # -# $Id: loncfile.pm,v 1.123 2015/01/19 15:36:11 goltermann Exp $ +# $Id: loncfile.pm,v 1.126 2023/07/14 14:32:57 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -109,13 +109,13 @@ sub Debug { } sub done { - my ($url) = @_; + my ($destfn) = @_; return '

' .&Apache::lonhtmlcommon::confirm_success(&mt("Done")) - .'
'.&mt("Continue").'' + .'
'.&mt("Continue").'' .'' .'

'; } @@ -167,11 +167,15 @@ sub URLToPath { } sub url { - my $fn=shift; + my ($fn,$context) = @_; my $londocroot = $Apache::lonnet::perlvar{'lonDocRoot'}; $fn=~ s/^\Q$londocroot\E//; $fn=~s{/\./}{/}g; - $fn=&HTML::Entities::encode($fn,'<>"&'); + if ($context eq 'js') { + &js_escape(\$fn); + } else { + $fn=&HTML::Entities::encode($fn,'\'<>"&'); + } return $fn; } @@ -279,28 +283,28 @@ sub exists { $published=~s{^\Q$londocroot/priv/\E}{$londocroot/res/}; my ($type,$result); if ( -d $construct ) { - return ('error','

'.&mt('Error: destination for operation is an existing directory.').'

'); + return ('error','

'.&mt('Error: destination for operation is an existing directory.').'

'); } if ( -e $published) { if ( -e $construct ) { $type = 'warning'; - $result.='

'.&mt('Warning: target file exists, and has been published!').'

'; + $result.='

'.&mt('Warning: target file exists, and has been published!').'

'; } else { my $published_type = (-d $published) ? 'directory' : 'file'; if ($published_type eq $creating) { $type = 'warning'; - $result.='

'.&mt("Warning: a published $published_type of this name exists.").'

'; + $result.='

'.&mt("Warning: a published $published_type of this name exists.").'

'; } else { $type = 'error'; - $result.='

'.&mt("Error: a published $published_type of this name exists.").'

'; + $result.='

'.&mt("Error: a published $published_type of this name exists.").'

'; } } } elsif ( -e $construct) { $type = 'warning'; - $result.='

'.&mt('Warning: target file exists!').'

'; + $result.='

'.&mt('Warning: target file exists!').'

'; } return ($type,$result); @@ -344,15 +348,16 @@ sub checksuffix { if ($old=~m:(.*)/+([^/]+)\.(\w+)$:) { $oldsuffix=$3; } if (lc($oldsuffix) ne lc($newsuffix)) { $result.= - '

'.&mt('Warning: change of MIME type!').'

'; + '

'.&mt('Warning: change of MIME type!').'>

'; } return $result; } sub cleanDest { - my ($request,$dest,$subdir,$fn,$uname,$udom)=@_; + my ($dest,$subdir,$fn,$uname,$udom)=@_; #remove bad characters my $foundbad=0; + my $warnings; my $error=''; if ($subdir && $dest =~/\./) { $foundbad=1; @@ -367,30 +372,29 @@ sub cleanDest { my ($newpath)=($dest=~m|(.*)/|); ($newpath,$error)=&relativeDest($fn,$newpath,$uname,$udom); if (! -d "$newpath") { - $request->print('

' - .&mt("You have requested to create file in directory [_1] which doesn't exist. The requested directory path has been removed from the requested filename." - ,&display($newpath)) - .'

'); + $warnings = '

' + .&mt("You have requested to create file in directory [_1] which doesn't exist. The requested directory path has been removed from the requested filename." + ,&display($newpath)) + .'

'; $dest=~s|.*/||; } } - if ($dest =~ /\.(\d+)\.(\w+)$/){ - $request->print('

' - .&mt('Bad filename [_1]',&display($dest)) - .'
' - .&mt('[_1](name).(number).(extension)[_2] not allowed.','','') - .'
' - .&mt('Removing the [_1].number.[_2] from requested filename.','','') - .'

'); + if ($dest =~ /\.(\d+)\.(\w+)$/) { + $warnings .= '

' + .&mt('Bad filename [_1]',&display($dest)) + .'
' + .&mt('[_1](name).(number).(extension)[_2] not allowed.','','') + .'
' + .&mt('Removing the [_1].number.[_2] from requested filename.','','') + .'

'; $dest =~ s/\.(\d+)(\.\w+)$/$2/; } if ($foundbad) { - $request->print('

' - .&mt('Invalid characters in requested name have been removed.') - .'

' - ); + $warnings .= '

' + .&mt('Invalid characters in requested name have been removed.') + .'

'; } - return ($dest,$error); + return ($dest,$error,$warnings); } sub relativeDest { @@ -469,7 +473,7 @@ Parameters: sub CloseForm2 { my ($request, $user, $fn) = @_; - $request->print(&done(&url($fn))); + $request->print(&done($fn)); } =pod @@ -840,6 +844,9 @@ Parameters: =item $newfilename - Name of the file to be created; no path information + +=item $warnings - Information about changes to filename made by cleanDest(). + =back Side Effects: @@ -856,8 +863,8 @@ button which returns you to the director =cut sub NewFile1 { - my ($request, $user, $domain, $fn, $newfilename) = @_; - return if (&filename_check($newfilename) ne 'ok'); + my ($request, $user, $domain, $fn, $newfilename, $warnings) = @_; + return if (&filename_check($newfilename,$warnings) ne 'ok'); if ($env{'form.action'} =~ /new(.+)file/) { my $extension=$1; @@ -870,8 +877,8 @@ sub NewFile1 { } } my ($type, $result)=&exists($user,$domain,$newfilename); - $request->print($result); if ($type eq 'error') { + $request->print($warnings.$result); $request->print(''); } else { my $extension; @@ -883,6 +890,7 @@ sub NewFile1 { my @okexts = qw(xml html xhtml htm xhtm problem page sequence rights sty task library js css txt); if (($extension eq '') || (!grep(/^\Q$extension\E/,@okexts))) { my $validexts = '.'.join(', .',@okexts); + $request->print($warnings.$result); $request->print('

'. &mt('Invalid filename: ').&display($newfilename).'

'. &mt('The name of the new file needs to end with an appropriate file extension to indicate the type of file to create.').'
'. @@ -895,14 +903,15 @@ sub NewFile1 { '

'. '

'); - } elsif ($type ne 'warning') { + } elsif (($type ne 'warning') && ($warnings eq '') && ($result eq '')) { my $query = ""; $query .= "?mode=" . $env{'form.mode'} unless (!exists($env{'form.mode'}) || !length($env{'form.mode'})); $request->print(' '); } else { + $request->print($warnings.$result); $request->print('

'.&mt('Make new file').' '.&display($newfilename).'?

'); $request->print(''); $request->print('
'.$error.''. '

'.&mt('Return to Directory'). '

'); @@ -986,49 +998,57 @@ sub phaseone { ''. ''. ''); - - if ($env{'form.action'} eq 'rename') { - &Rename1($r, $uname, $udom, $fn, $newfilename, 'rename'); - } elsif ($env{'form.action'} eq 'move') { - &Rename1($r, $uname, $udom, $fn, $newfilename, 'move'); - } elsif ($env{'form.action'} eq 'delete') { - &Delete1($r, $uname, $udom, $fn); - } elsif ($env{'form.action'} eq 'decompress') { - &Decompress1($r, $uname, $udom, $fn); - } elsif ($env{'form.action'} eq 'copy') { - if($newfilename) { - &Copy1($r, $uname, $udom, $fn, $newfilename); - } else { - $r->print('

' - .&mt('No new filename specified.') - .'

' - ); - } - } elsif ($env{'form.action'} eq 'newdir') { - my $mode = ''; - if (exists($env{'form.callingmode'}) ) { - $mode = $env{'form.callingmode'}; - } - &NewDir1($r, $uname, $udom, $fn, $newfilename, $mode); - } elsif ($env{'form.action'} eq 'newfile' || - $env{'form.action'} eq 'newhtmlfile' || - $env{'form.action'} eq 'newproblemfile' || - $env{'form.action'} eq 'newpagefile' || - $env{'form.action'} eq 'newsequencefile' || - $env{'form.action'} eq 'newrightsfile' || - $env{'form.action'} eq 'newstyfile' || - $env{'form.action'} eq 'newtaskfile' || - $env{'form.action'} eq 'newlibraryfile' || - $env{'form.action'} eq 'Select Action') { + + if ($env{'form.action'} eq 'newfile' || + $env{'form.action'} eq 'newhtmlfile' || + $env{'form.action'} eq 'newproblemfile' || + $env{'form.action'} eq 'newpagefile' || + $env{'form.action'} eq 'newsequencefile' || + $env{'form.action'} eq 'newrightsfile' || + $env{'form.action'} eq 'newstyfile' || + $env{'form.action'} eq 'newtaskfile' || + $env{'form.action'} eq 'newlibraryfile' || + $env{'form.action'} eq 'Select Action') { my $empty=&mt('Type Name Here'); - if (($newfilename!~/\/$/) && ($newfilename!~/$empty$/)) { - &NewFile1($r, $uname, $udom, $fn, $newfilename); - } else { + if (($newfilename!~/\/$/) && ($newfilename!~/$empty$/)) { + &NewFile1($r, $uname, $udom, $fn, $newfilename, $warnings); + } else { + if ($warnings) { + $r->print($warnings); + } $r->print('

' .&mt('No new filename specified.') .'

' ); - } + } + } else { + if ($warnings) { + $r->print($warnings); + } + if ($env{'form.action'} eq 'rename') { + &Rename1($r, $uname, $udom, $fn, $newfilename, 'rename'); + } elsif ($env{'form.action'} eq 'move') { + &Rename1($r, $uname, $udom, $fn, $newfilename, 'move'); + } elsif ($env{'form.action'} eq 'delete') { + &Delete1($r, $uname, $udom, $fn); + } elsif ($env{'form.action'} eq 'decompress') { + &Decompress1($r, $uname, $udom, $fn); + } elsif ($env{'form.action'} eq 'copy') { + if ($newfilename) { + &Copy1($r, $uname, $udom, $fn, $newfilename); + } else { + $r->print('

' + .&mt('No new filename specified.') + .'

' + ); + } + } elsif ($env{'form.action'} eq 'newdir') { + my $mode = ''; + if (exists($env{'form.callingmode'}) ) { + $mode = $env{'form.callingmode'}; + } + &NewDir1($r, $uname, $udom, $fn, $newfilename, $mode); + } } } @@ -1417,7 +1437,7 @@ sub phasetwo { [''.&mt('Return to Directory').'', ''.$disp_newname.''])); } else { - $r->print(&done(&url($dest))); + $r->print(&done($dest)); } } } @@ -1457,7 +1477,7 @@ sub handler { return HTTP_NOT_FOUND; } - unless ($fn) { + unless ($fn) { &Debug($r, "loncfile::handler - doctored url is empty"); $r->log_reason($env{'user.name'}.' at '.$env{'user.domain'}. ' trying to cfile non-existing file', $r->filename); @@ -1500,20 +1520,33 @@ function writeDone() { my $londocroot = $r->dir_config('lonDocRoot'); my $trailfile = $fn; $trailfile =~ s{^/(priv/)}{$londocroot/$1}; - + # Breadcrumbs + my $crsauthor; + my $text = 'Authoring Space'; + my $title = 'Authoring Space File Operation', + my $href = &Apache::loncommon::authorspace(&url($fn)); + if ($env{'request.course.id'}) { + my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + if ($href eq "/priv/$cdom/$cnum/") { + $text = 'Course Authoring Space'; + $title = 'Course Authoring Space File Operation', + $crsauthor = 1; + } + } &Apache::lonhtmlcommon::clear_breadcrumbs(); &Apache::lonhtmlcommon::add_breadcrumb({ - 'text' => 'Authoring Space', - 'href' => &Apache::loncommon::authorspace($fn), + 'text' => $text, + 'href' => $href, }); &Apache::lonhtmlcommon::add_breadcrumb({ 'text' => 'File Operation', - 'title' => 'Authoring Space File Operation', + 'title' => $title, 'href' => '', }); - $r->print(&Apache::loncommon::start_page('Authoring Space File Operation', + $r->print(&Apache::loncommon::start_page($title, $js, {'add_entries' => \%loaditem,}) .&Apache::lonhtmlcommon::breadcrumbs() @@ -1524,10 +1557,12 @@ function writeDone() { $r->print('

'.&mt('Location').': '.&display($fn).'

'); if (($uname ne $env{'user.name'}) || ($udom ne $env{'user.domain'})) { - $r->print('

' - .&mt('Co-Author [_1]',$uname.':'.$udom) - .'

' - ); + unless ($crsauthor) { + $r->print('

' + .&mt('Co-Author [_1]',$uname.':'.$udom) + .'

' + ); + } } @@ -1551,6 +1586,25 @@ function writeDone() { 'Select Action' => 'New Resource', ); if ($action{$env{'form.action'}}) { + if ($crsauthor) { + my @disallowed = qw(page sequence rights library); + my $newtype; + if ($env{'form.action'} =~ /^new(\w+)file$/) { + $newtype = $1; + } elsif ($env{'form.action'} eq 'newfile') { + ($newtype) = ($env{'form.newfilename'} =~ m{\.([^/.]+)$}); + $newtype = lc($newtype); + } + if (($newtype ne '') && + (grep(/^\Q$newtype\E$/,@disallowed))) { + $r->print('

' + .&mt('Creation of a new file of type: [_1] is not permitted in Course Authoring Space',$newtype) + .'

' + .&Apache::loncommon::end_page() + ); + return OK; + } + } $r->print('

'.$action{$env{'form.action'}}.'

'); } else { $r->print('

'