--- loncom/interface/portfolio.pm	2016/06/10 22:31:27	1.257
+++ loncom/interface/portfolio.pm	2021/11/30 15:55:37	1.265
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # portfolio browser
 #
-# $Id: portfolio.pm,v 1.257 2016/06/10 22:31:27 raeburn Exp $
+# $Id: portfolio.pm,v 1.265 2021/11/30 15:55:37 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -121,8 +121,8 @@ END
                  .'<fieldset>'
                  .'<legend>'.$lt{'upload_label'}.'</legend>'
                  .$groupitem 
-                 .'<input name="uploaddoc" type="file" class="flUpload" />'
-                 .'<input type="hidden" id="free_space" value="'.$free_space.'" />'
+                 .'<input name="uploaddoc" type="file" class="LC_flUpload" />'
+                 .'<input type="hidden" id="LC_free_space" value="'.$free_space.'" />'
                  .'<input type="hidden" name="currentpath" value="'.$current_path.'" />'
                  .'<input type="hidden" name="action" value="'.$env{"form.action"}.'" />'
                  .'<input type="hidden" name="symb" value="'.$env{"form.symb"}.'" />'
@@ -909,13 +909,13 @@ sub display_access {
         $info .= '</li><li>'.&mt('Passphrase-protected files do not require log-in, but will require the viewer to enter the passphrase you set.');
         $info .= '</li><li>'.&explain_conditionals();
         $info .= '</li></ul>'.
-                  &mt('A listing of files viewable without log-in is available at: ')."<a href=\"/adm/$udom/$uname/aboutme/portfolio\">".&Apache::lonnet::absolute_url($ENV{'SERVER_NAME'})."/adm/$udom/$uname/aboutme/portfolio</a>.<br />";
+                  &mt('A listing of files viewable without log-in is available at: ')."<a href=\"/adm/$udom/$uname/aboutme/portfolio\">".&Apache::lonnet::absolute_url()."/adm/$udom/$uname/aboutme/portfolio</a>.<br />";
         if ($group eq '') {
             $info .= &mt("For logged in users a 'Display file listing' link will also appear (when there are viewable files) on your personal information page:");
         } else {
             $info .= &mt("For logged in users a 'Display file listing' link will also appear (when there are viewable files) on the course information page:");
         }
-        $info .= "<br /><a href=\"/adm/$udom/$uname/aboutme\">".&Apache::lonnet::absolute_url($ENV{'SERVER_NAME'})."/adm/$udom/$uname/aboutme</a><br />";
+        $info .= "<br /><a href=\"/adm/$udom/$uname/aboutme\">".&Apache::lonnet::absolute_url()."/adm/$udom/$uname/aboutme</a><br />";
         if ($group ne '') {
             $info .= &mt("Users with course editing rights may add a 'Group Portfolio' item using the Course Editor (Collaboration tab), to provide access to viewable group portfolio files.").'<br />';
         }
@@ -1073,7 +1073,7 @@ sub build_access_summary {
                     $r->print(&mt('Users: ').$curr_user_list);
                 } elsif ($scope eq 'ip') {
                     my $curr_ips_list = &sort_ips($content->{'ip'});
-                    $r->print(&mt('IP(s): ').$curr_ips_list);
+                    $r->print(&mt('IP(s):').' '.$curr_ips_list);
                 } else {
                     $r->print('&nbsp;');
                 }
@@ -2549,13 +2549,15 @@ sub coursegrp_portfolio_header {
     }
     &Apache::lonhtmlcommon::add_breadcrumb
         ({href=>"/adm/$cdom/$cnum/$env{'form.group'}/smppg?ref=$env{'form.ref'}",
-          text=>"$ucgpterm: $grp_desc",
-          title=>"Go to group's home page"},
+          text=>&mt('Group').": $grp_desc",
+          title=>&mt("Go to group's home page"),
+          no_mt=>1},
          {href=>"/adm/coursegrp_portfolio?".&group_args(),
           text=>"Group Portfolio",
           title=>"Display group portfolio"});
     my $output = &Apache::lonhtmlcommon::breadcrumbs(
-                         &mt('[_1] portfolio files - [_2]',$gpterm,$grp_desc));
+                         &mt('Group portfolio files - [_1]',$grp_desc),
+                                                     undef,undef,undef,undef,1);
     return $output;
 }
 
@@ -2615,6 +2617,45 @@ sub free_space {
     return $free_space;
 }
 
+sub valid_container {
+    my ($uname,$udom,$group) = @_;
+    my $container_prefix;
+    if ($group ne '') {
+        $container_prefix = "/uploaded/$udom/$uname/groups/$group/portfolio";
+    } else {
+        $container_prefix = "/uploaded/$udom/$uname/portfolio";
+    }
+    if ($env{'form.currentpath'}) {
+        $container_prefix .= $env{'form.currentpath'};
+    } else {
+        $container_prefix .= '/';
+    }
+    if ($env{'form.container'} =~ m{^\Q$container_prefix\E(.+)$}) {
+        my $filename = $1;
+        if ($filename eq &Apache::lonnet::clean_filename($filename)) {
+            return 1;
+        }
+    }
+    return;
+}
+
+sub invalid_parms {
+    my ($r,$url,$currentpath) = @_;
+    my $escpath = &HTML::Entities::encode($currentpath,'&<>"');
+    my $rtnlink = '<a href="'.$url;
+    if ($url =~ /\?/) {
+        $rtnlink .= '&';
+    } else {
+        $rtnlink .= '?';
+    }
+    $rtnlink .= 'currentpath='.$escpath;
+    $rtnlink .= '">'.&mt('Return to directory').'</a>';
+    $r->print('<h3>'.&mt('Action disallowed').'</h3>');
+    $r->print(&mt('Some of the data included with this request were invalid'));
+    $r->print('<br />'.$rtnlink);
+    return;
+}
+
 sub handler {
     # this handles file management
     my $r = shift;
@@ -2728,8 +2769,9 @@ sub handler {
     }
     $r->rflush();
     # Check if access to portfolio is blocked by one or more blocking events in courses.
+    my $clientip = &Apache::lonnet::get_requestor_ip($r);
     my ($blocked,$blocktext) = 
-        &Apache::loncommon::blocking_status('port',$uname,$udom);
+        &Apache::loncommon::blocking_status('port',$clientip,$uname,$udom);
     if ($blocked) {
         my $evade_block;
         # If portfolio display is in a window popped up from a "Select Portfolio Files"
@@ -2763,6 +2805,21 @@ sub handler {
             $r->print(&Apache::loncommon::end_page());
             return OK;
         }
+    }
+    if (($env{'form.currentpath'}) && ($env{'form.currentpath'} ne '/')) {
+        my $clean_currentpath = '/'.&Apache::loncommon::clean_path($env{'form.currentpath'}).'/';
+        unless ($env{'form.currentpath'} eq $clean_currentpath) {
+            &invalid_parms($r,$url);
+            $r->print(&Apache::loncommon::end_page());
+            return OK;
+        }
+    }
+    if ($env{'form.container'}) {
+        unless (&valid_container($uname,$udom,$group)) {
+            &invalid_parms($r,$url,$env{'form.currentpath'});
+            $r->print(&Apache::loncommon::end_page());
+            return OK;
+        }
     }
     if (($env{'form.storeupl'}) & (!$env{'form.uploaddoc.filename'})){
    	$r->print(