--- loncom/interface/loncommon.pm	2009/10/31 05:47:10	1.906
+++ loncom/interface/loncommon.pm	2011/06/06 21:25:59	1.1010
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # a pile of common routines
 #
-# $Id: loncommon.pm,v 1.906 2009/10/31 05:47:10 raeburn Exp $
+# $Id: loncommon.pm,v 1.1010 2011/06/06 21:25:59 www Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -409,7 +409,7 @@ sub studentbrowser_javascript {
 <script type="text/javascript" language="Javascript">
 // <![CDATA[
     var stdeditbrowser;
-    function openstdbrowser(formname,uname,udom,roleflag,ignorefilter,courseadvonly) {
+    function openstdbrowser(formname,uname,udom,clicker,roleflag,ignorefilter,courseadvonly) {
         var url = '/adm/pickstudent?';
         var filter;
 	if (!ignorefilter) {
@@ -421,7 +421,8 @@ sub studentbrowser_javascript {
 	   }
         }
         url += 'form=' + formname + '&unameelement='+uname+
-                                    '&udomelement='+udom;
+                                    '&udomelement='+udom+
+                                    '&clicker='+clicker;
 	if (roleflag) { url+="&roles=1"; }
         if (courseadvonly) { url+="&courseadvonly=1"; }
         var title = 'Student_Browser';
@@ -435,15 +436,37 @@ sub studentbrowser_javascript {
 ENDSTDBRW
 }
 
+sub resourcebrowser_javascript {
+   unless ($env{'request.course.id'}) { return ''; }
+   return (<<'ENDRESBRW');
+<script type="text/javascript" language="Javascript">
+// <![CDATA[
+    var reseditbrowser;
+    function openresbrowser(formname,reslink) {
+        var url = '/adm/pickresource?form='+formname+'&reslink='+reslink;
+        var title = 'Resource_Browser';
+        var options = 'scrollbars=1,resizable=1,menubar=0';
+        options += ',width=700,height=500';
+        reseditbrowser = open(url,title,options,'1');
+        reseditbrowser.focus();
+    }
+// ]]>
+</script>
+ENDRESBRW
+}
+
 sub selectstudent_link {
-   my ($form,$unameele,$udomele,$courseadvonly)=@_;
-   my $callargs = "'".$form."','".$unameele."','".$udomele."'";
+   my ($form,$unameele,$udomele,$courseadvonly,$clickerid)=@_;
+   my $callargs = "'".&Apache::lonhtmlcommon::entity_encode($form)."','".
+                      &Apache::lonhtmlcommon::entity_encode($unameele)."','".
+                      &Apache::lonhtmlcommon::entity_encode($udomele)."'";
    if ($env{'request.course.id'}) {  
        if (!&Apache::lonnet::allowed('srm',$env{'request.course.id'})
 	   && !&Apache::lonnet::allowed('srm',$env{'request.course.id'}.
 					'/'.$env{'request.course.sec'})) {
 	   return '';
        }
+       $callargs.=",'".&Apache::lonhtmlcommon::entity_encode($clickerid)."'";
        if ($courseadvonly)  {
            $callargs .= ",'',1,1";
        }
@@ -460,6 +483,19 @@ sub selectstudent_link {
    return '';
 }
 
+sub selectresource_link {
+   my ($form,$reslink,$arg)=@_;
+   
+   my $callargs = "'".&Apache::lonhtmlcommon::entity_encode($form)."','".
+                      &Apache::lonhtmlcommon::entity_encode($reslink)."'";
+   unless ($env{'request.course.id'}) { return $arg; }
+   return '<span class="LC_nobreak">'.
+              '<a href="javascript:openresbrowser('.$callargs.');">'.
+              $arg.'</a></span>';
+}
+
+
+
 sub authorbrowser_javascript {
     return <<"ENDAUTHORBRW";
 <script type="text/javascript" language="JavaScript">
@@ -482,8 +518,11 @@ ENDAUTHORBRW
 }
 
 sub coursebrowser_javascript {
-    my ($domainfilter,$sec_element,$formname,$role_element)=@_;
-    my $crs_or_grp_alert = &mt('Please select the type of LON-CAPA entity - Course or Community - for which you wish to add/modify a user role.');
+    my ($domainfilter,$sec_element,$formname,$role_element,$crstype) = @_;
+    my $wintitle = 'Course_Browser';
+    if ($crstype eq 'Community') {
+        $wintitle = 'Community_Browser';
+    }
     my $id_functions = &javascript_index_functions();
     my $output = '
 <script type="text/javascript" language="JavaScript">
@@ -491,7 +530,7 @@ sub coursebrowser_javascript {
     var stdeditbrowser;'."\n";
 
     $output .= <<"ENDSTDBRW";
-    function opencrsbrowser(formname,uname,udom,desc,extra_element,multflag,crstype) {
+    function opencrsbrowser(formname,uname,udom,desc,extra_element,multflag,type,type_elem) {
         var url = '/adm/pickcourse?';
         var formid = getFormIdByName(formname);
         var domainfilter = getDomainFromSelectbox(formname,udom);
@@ -520,6 +559,12 @@ sub coursebrowser_javascript {
                 }
             }     
         }
+        if (type != null && type != '') {
+            url += '&type='+type;
+        }
+        if (type_elem != null && type_elem != '') {
+            url += '&typeelement='+type_elem;
+        }
         if (formname == 'ccrs') {
             var ownername = document.forms[formid].ccuname.value;
             var ownerdom =  document.forms[formid].ccdomain.options[document.forms[formid].ccdomain.selectedIndex].value;
@@ -528,19 +573,7 @@ sub coursebrowser_javascript {
         if (multflag !=null && multflag != '') {
             url += '&multiple='+multflag;
         }
-        if (crstype == 'Course/Community') {
-            if (formname == 'cu') {
-                crstype = document.cu.crstype.options[document.cu.crstype.selectedIndex].value; 
-                if (crstype == "") {
-                    alert("$crs_or_grp_alert");
-                    return;
-                }
-            }
-        }
-        if (crstype !=null && crstype != '') {
-            url += '&type='+crstype;
-        }
-        var title = 'Course_Browser';
+        var title = '$wintitle';
         var options = 'scrollbars=1,resizable=1,menubar=0';
         options += ',width=700,height=600';
         stdeditbrowser = open(url,title,options,'1');
@@ -760,19 +793,21 @@ function setRole(crstype) {
 }
 
 sub selectcourse_link {
-   my ($form,$unameele,$udomele,$desc,$extra_element,$multflag,$selecttype)=@_;
+   my ($form,$unameele,$udomele,$desc,$extra_element,$multflag,$selecttype,
+       $typeelement) = @_;
+   my $type = $selecttype;
    my $linktext = &mt('Select Course');
    if ($selecttype eq 'Community') {
-       $linktext = &mt('Select Community'); 
+       $linktext = &mt('Select Community');
    } elsif ($selecttype eq 'Course/Community') {
        $linktext = &mt('Select Course/Community');
-       $selecttype = 'Course';
+       $type = '';
    }
    return '<span class="LC_nobreak">'
          ."<a href='"
          .'javascript:opencrsbrowser("'.$form.'","'.$unameele
          .'","'.$udomele.'","'.$desc.'","'.$extra_element
-         .'","'.$multflag.'","'.$selecttype.'");'
+         .'","'.$multflag.'","'.$type.'","'.$typeelement.'");'
          ."'>".$linktext.'</a>'
          .'</span>';
 }
@@ -901,7 +936,7 @@ sub select_language {
             $langchoices{$code} = &plainlanguagedescription($id);
         }
     }
-    return &select_form($selected,$name,%langchoices);
+    return &select_form($selected,$name,\%langchoices);
 }
 
 =pod
@@ -1073,7 +1108,7 @@ END
 
 =pod
 
-=item * &help_open_topic($topic,$text,$stayOnPage,$width,$height)
+=item * &help_open_topic($topic,$text,$stayOnPage,$width,$height,$imgid)
 
 Returns a string corresponding to an HTML link to the given help
 $topic, where $topic corresponds to the name of a .tex file in
@@ -1091,12 +1126,16 @@ a new window using Javascript. (Default
 
 $width and $height are optional numerical parameters that will
 override the width and height of the popped up window, which may
-be useful for certain help topics with big pictures included. 
+be useful for certain help topics with big pictures included.
+
+$imgid is the id of the img tag used for the help icon. This may be
+used in a javascript call to switch the image src.  See 
+lonhtmlcommon::htmlareaselectactive() for an example.
 
 =cut
 
 sub help_open_topic {
-    my ($topic, $text, $stayOnPage, $width, $height) = @_;
+    my ($topic, $text, $stayOnPage, $width, $height, $imgid) = @_;
     $text = "" if (not defined $text);
     $stayOnPage = 0 if (not defined $stayOnPage);
     $width = 350 if (not defined $width);
@@ -1125,10 +1164,13 @@ sub help_open_topic {
     # (Always) Add the graphic
     my $title = &mt('Online Help');
     my $helpicon=&lonhttpdurl("/adm/help/help.png");
+    if ($imgid ne '') {
+        $imgid = ' id="'.$imgid.'"';
+    }
     $template.=' <a target="_top" href="'.$link.'" title="'.$title.'">'
               .'<img src="'.$helpicon.'" border="0"'
               .' alt="'.&mt('Help: [_1]',$topic).'"'
-              .' title="'.$title.'"' 
+              .' title="'.$title.'" style="vertical-align:middle;"'.$imgid 
               .' /></a>';
     if ($text ne "") {	
         $template.='</span>';
@@ -1171,7 +1213,7 @@ sub general_help {
     my $helptopic='Student_Intro';
     if ($env{'request.role'}=~/^(ca|au)/) {
 	$helptopic='Authoring_Intro';
-    } elsif ($env{'request.role'}=~/^cc/) {
+    } elsif ($env{'request.role'}=~/^(cc|co)/) {
 	$helptopic='Course_Coordination_Intro';
     } elsif ($env{'request.role'}=~/^dc/) {
         $helptopic='Domain_Coordination_Intro';
@@ -1203,12 +1245,7 @@ ENDOUTPUT
 sub help_open_menu {
     my ($topic,$component_help,$faq,$bug,$stayOnPage,$width,$height,$text) 
 	= @_;    
-    $stayOnPage = 0 if (not defined $stayOnPage);
-    # only use pop-up help (stayOnPage == 0)
-    # if environment.remote is on (using remote control UI)
-    if ($env{'environment.remote'} eq 'off' ) {
-        $stayOnPage=1;
-    }
+    $stayOnPage = 1;
     my $output;
     if ($component_help) {
 	if (!$text) {
@@ -1229,8 +1266,8 @@ sub help_open_menu {
 sub top_nav_help {
     my ($text) = @_;
     $text = &mt($text);
-    my $stay_on_page = 
-	($env{'environment.remote'} eq 'off' );
+    my $stay_on_page = 1;
+
     my $link = ($stay_on_page) ? "javascript:helpMenu('display')"
 	                     : "javascript:helpMenu('open')";
     my $banner_link = &update_help_link(undef,undef,undef,undef,$stay_on_page);
@@ -1245,10 +1282,7 @@ END
 
 sub help_menu_js {
     my ($text) = @_;
-
-    my $stayOnPage = 
-	($env{'environment.remote'} eq 'off' );
-
+    my $stayOnPage = 1;
     my $width = 620;
     my $height = 600;
     my $helptopic=&general_help();
@@ -1305,10 +1339,7 @@ sub help_open_bug {
     unless ($env{'user.adv'}) { return ''; }
     unless ($Apache::lonnet::perlvar{'BugzillaHost'}) { return ''; }
     $text = "" if (not defined $text);
-    $stayOnPage = 0 if (not defined $stayOnPage);
-    if ($env{'environment.remote'} eq 'off' ) {
 	$stayOnPage=1;
-    }
     $width = 600 if (not defined $width);
     $height = 600 if (not defined $height);
 
@@ -1349,10 +1380,7 @@ sub help_open_faq {
     unless ($env{'user.adv'}) { return ''; }
     unless ($Apache::lonnet::perlvar{'FAQHost'}) { return ''; }
     $text = "" if (not defined $text);
-    $stayOnPage = 0 if (not defined $stayOnPage);
-    if ($env{'environment.remote'} eq 'off' ) {
 	$stayOnPage=1;
-    }
     $width = 350 if (not defined $width);
     $height = 400 if (not defined $height);
 
@@ -1720,10 +1748,13 @@ sub create_workbook {
     my $workbook  = Spreadsheet::WriteExcel->new('/home/httpd'.$filename);
     if (! defined($workbook)) {
         $r->log_error("Error creating excel spreadsheet $filename: $!");
-        $r->print('<p>'.&mt("Unable to create new Excel file.  ".
-                            "This error has been logged.  ".
-                            "Please alert your LON-CAPA administrator").
-                  '</p>');
+        $r->print(
+            '<p class="LC_error">'
+           .&mt('Problems occurred in creating the new Excel file.')
+           .' '.&mt('This error has been logged.')
+           .' '.&mt('Please alert your LON-CAPA administrator.')
+           .'</p>'
+        );
         return (undef);
     }
     #
@@ -1763,9 +1794,13 @@ sub create_text_file {
     $fh = Apache::File->new('>/home/httpd'.$filename);
     if (! defined($fh)) {
         $r->log_error("Couldn't open $filename for output $!");
-        $r->print(&mt('Problems occurred in creating the output file. '
-                     .'This error has been logged. '
-                     .'Please alert your LON-CAPA administrator.'));
+        $r->print(
+            '<p class="LC_error">'
+           .&mt('Problems occurred in creating the output file.')
+           .' '.&mt('This error has been logged.')
+           .' '.&mt('Please alert your LON-CAPA administrator.')
+           .'</p>'
+        );
     }
     return ($fh,$filename)
 }
@@ -1794,7 +1829,7 @@ sub domain_select {
 	return &multiple_select_form($name,$value,4,\%domains);
     } else {
 	$domains{'select_form_order'} = [sort {lc($a) cmp lc($b) } (keys(%domains))];
-	return &select_form($name,$value,%domains);
+	return &select_form($name,$value,\%domains);
     }
 }
 
@@ -1856,29 +1891,36 @@ sub multiple_select_form {
 
 =pod
 
-=item * &select_form($defdom,$name,%hash)
+=item * &select_form($defdom,$name,$hashref,$onchange)
 
 Returns a string containing a <select name='$name' size='1'> form to 
-allow a user to select options from a hash option_name => displayed text.  
+allow a user to select options from a ref to a hash containing:
+option_name => displayed text. An optional $onchange can include
+a javascript onchange item, e.g., onchange="this.form.submit();"  
+
 See lonrights.pm for an example invocation and use.
 
 =cut
 
 #-------------------------------------------
 sub select_form {
-    my ($def,$name,%hash) = @_;
-    my $selectform = "<select name=\"$name\" size=\"1\">\n";
+    my ($def,$name,$hashref,$onchange) = @_;
+    return unless (ref($hashref) eq 'HASH');
+    if ($onchange) {
+        $onchange = ' onchange="'.$onchange.'"';
+    }
+    my $selectform = "<select name=\"$name\" size=\"1\"$onchange>\n";
     my @keys;
-    if (exists($hash{'select_form_order'})) {
-	@keys=@{$hash{'select_form_order'}};
+    if (exists($hashref->{'select_form_order'})) {
+	@keys=@{$hashref->{'select_form_order'}};
     } else {
-	@keys=sort(keys(%hash));
+	@keys=sort(keys(%{$hashref}));
     }
     foreach my $key (@keys) {
         $selectform.=
 	    '<option value="'.&HTML::Entities::encode($key,'"<>&').'" '.
             ($key eq $def ? 'selected="selected" ' : '').
-                ">".&mt($hash{$key})."</option>\n";
+                ">".$hashref->{$key}."</option>\n";
     }
     $selectform.="</select>";
     return $selectform;
@@ -1896,9 +1938,9 @@ sub display_filter {
            &mt('Filter [_1]',
 	   &select_form($env{'form.displayfilter'},
 			'displayfilter',
-			('currentfolder' => 'Current folder/page',
+			{'currentfolder' => 'Current folder/page',
 			 'containing' => 'Containing phrase',
-			 'none' => 'None'))).
+			 'none' => 'None'})).
 			 '<input type="text" name="containingphrase" size="30" value="'.&HTML::Entities::encode($env{'form.containingphrase'}).'" /></span>';
 }
 
@@ -1943,7 +1985,7 @@ sub select_level_form {
 
 =pod
 
-=item * &select_dom_form($defdom,$name,$includeempty,$showdomdesc,$onchange)
+=item * &select_dom_form($defdom,$name,$includeempty,$showdomdesc,$onchange,$incdoms)
 
 Returns a string containing a <select name='$name' size='1'> form to 
 allow a user to select the domain to preform an operation in.  
@@ -1954,17 +1996,24 @@ selected");
 
 If the $showdomdesc flag is set, the domain name is followed by the domain description.
 
-The optional $onchange argumnet specifies what should occur if the domain selector is changed, e.g., 'this.form.submit()' if the form is to be automatically submitted.  
+The optional $onchange argument specifies what should occur if the domain selector is changed, e.g., 'this.form.submit()' if the form is to be automatically submitted.
+
+The optional $incdoms is a reference to an array of domains which will be the only available options. 
 
 =cut
 
 #-------------------------------------------
 sub select_dom_form {
-    my ($defdom,$name,$includeempty,$showdomdesc,$onchange) = @_;
+    my ($defdom,$name,$includeempty,$showdomdesc,$onchange,$incdoms) = @_;
     if ($onchange) {
         $onchange = ' onchange="'.$onchange.'"';
     }
-    my @domains = sort {lc($a) cmp lc($b)} (&Apache::lonnet::all_domains());
+    my @domains;
+    if (ref($incdoms) eq 'ARRAY') {
+        @domains = sort {lc($a) cmp lc($b)} (@{$incdoms});
+    } else {
+        @domains = sort {lc($a) cmp lc($b)} (&Apache::lonnet::all_domains());
+    }
     if ($includeempty) { @domains=('',@domains); }
     my $selectdomain = "<select name=\"$name\" size=\"1\"$onchange>\n";
     foreach my $dom (@domains) {
@@ -2261,12 +2310,16 @@ function changed_text(choice,currentform
 }
 
 function set_auth_radio_buttons(newvalue,currentform) {
+    var numauthchoices = currentform.login.length;
+    if (typeof numauthchoices  == "undefined") {
+        return;
+    } 
     var i=0;
-    while (i < currentform.login.length) {
+    while (i < numauthchoices) {
         if (currentform.login[i].value == newvalue) { break; }
         i++;
     }
-    if (i == currentform.login.length) {
+    if (i == numauthchoices) {
         return;
     }
     current.radiovalue = newvalue;
@@ -3233,8 +3286,7 @@ sub filemimetype {
 sub filecategoryselect {
     my ($name,$value)=@_;
     return &select_form($value,$name,
-			'' => &mt('Any category'),
-			map { $_,$_ } sort(keys(%category_extensions)));
+                        {'' => &mt('Any category'), map { $_,$_ } sort(keys(%category_extensions))});
 }
 
 =pod
@@ -3399,12 +3451,24 @@ sub get_previous_attempt {
       }
       $prevattempts=&start_data_table().&start_data_table_header_row();
       $prevattempts.='<th>'.&mt('History').'</th>';
+      my (%typeparts,%lasthidden);
+      my $showsurv=&Apache::lonnet::allowed('vas',$env{'request.course.id'});
       foreach my $key (sort(keys(%lasthash))) {
 	my ($ign,@parts) = split(/\./,$key);
 	if ($#parts > 0) {
 	  my $data=$parts[-1];
+          next if ($data eq 'foilorder');
 	  pop(@parts);
-	  $prevattempts.='<th>'.&mt('Part ').join('.',@parts).'<br />'.$data.'&nbsp;</th>';
+          $prevattempts.='<th>'.&mt('Part ').join('.',@parts).'<br />'.$data.'&nbsp;</th>';
+          if ($data eq 'type') {
+              unless ($showsurv) {
+                  my $id = join(',',@parts);
+                  $typeparts{$ign.'.'.$id} = $lasthash{$key};
+                  if (($lasthash{$key} eq 'anonsurvey') || ($lasthash{$key} eq 'anonsurveycred')) {
+                      $lasthidden{$ign.'.'.$id} = 1;
+                  }
+              }
+          } 
 	} else {
 	  if ($#parts == 0) {
 	    $prevattempts.='<th>'.$parts[0].'</th>';
@@ -3416,21 +3480,93 @@ sub get_previous_attempt {
       $prevattempts.=&end_data_table_header_row();
       if ($getattempt eq '') {
 	for ($version=1;$version<=$returnhash{'version'};$version++) {
-	  $prevattempts.=&start_data_table_row().
-	      '<td>'.&mt('Transaction [_1]',$version).'</td>';
-	    foreach my $key (sort(keys(%lasthash))) {
-		my $value = &format_previous_attempt_value($key,
-							   $returnhash{$version.':'.$key});
-		$prevattempts.='<td>'.$value.'&nbsp;</td>';   
-	    }
-	  $prevattempts.=&end_data_table_row();
+            my @hidden;
+            if (%typeparts) {
+                foreach my $id (keys(%typeparts)) {
+                    if (($returnhash{$version.':'.$id.'.type'} eq 'anonsurvey') || ($returnhash{$version.':'.$id.'.type'} eq 'anonsurveycred')) {
+                        push(@hidden,$id);
+                    }
+                }
+            }
+            $prevattempts.=&start_data_table_row().
+                           '<td>'.&mt('Transaction [_1]',$version).'</td>';
+            if (@hidden) {
+                foreach my $key (sort(keys(%lasthash))) {
+                    next if ($key =~ /\.foilorder$/);
+                    my $hide;
+                    foreach my $id (@hidden) {
+                        if ($key =~ /^\Q$id\E/) {
+                            $hide = 1;
+                            last;
+                        }
+                    }
+                    if ($hide) {
+                        my ($id,$data) = ($key =~ /^(.+)\.([^.]+)$/);
+                        if (($data eq 'award') || ($data eq 'awarddetail')) {
+                            my $value = &format_previous_attempt_value($key,
+                                             $returnhash{$version.':'.$key});
+                            $prevattempts.='<td>'.$value.'&nbsp;</td>';
+                        } else {
+                            $prevattempts.='<td>&nbsp;</td>';
+                        }
+                    } else {
+                        if ($key =~ /\./) {
+                            my $value = &format_previous_attempt_value($key,
+                                              $returnhash{$version.':'.$key});
+                            $prevattempts.='<td>'.$value.'&nbsp;</td>';
+                        } else {
+                            $prevattempts.='<td>&nbsp;</td>';
+                        }
+                    }
+                }
+            } else {
+	        foreach my $key (sort(keys(%lasthash))) {
+                    next if ($key =~ /\.foilorder$/);
+		    my $value = &format_previous_attempt_value($key,
+			            $returnhash{$version.':'.$key});
+		    $prevattempts.='<td>'.$value.'&nbsp;</td>';
+	        }
+            }
+	    $prevattempts.=&end_data_table_row();
 	 }
       }
+      my @currhidden = keys(%lasthidden);
       $prevattempts.=&start_data_table_row().'<td>'.&mt('Current').'</td>';
       foreach my $key (sort(keys(%lasthash))) {
-	my $value = &format_previous_attempt_value($key,$lasthash{$key});
-	if ($key =~/$regexp$/ && (defined &$gradesub)) {$value = &$gradesub($value)}
-	$prevattempts.='<td>'.$value.'&nbsp;</td>';
+          next if ($key =~ /\.foilorder$/);
+          if (%typeparts) {
+              my $hidden;
+              foreach my $id (@currhidden) {
+                  if ($key =~ /^\Q$id\E/) {
+                      $hidden = 1;
+                      last;
+                  }
+              }
+              if ($hidden) {
+                  my ($id,$data) = ($key =~ /^(.+)\.([^.]+)$/);
+                  if (($data eq 'award') || ($data eq 'awarddetail')) {
+                      my $value = &format_previous_attempt_value($key,$lasthash{$key});
+                      if ($key =~/$regexp$/ && (defined &$gradesub)) {
+                          $value = &$gradesub($value);
+                      }
+                      $prevattempts.='<td>'.$value.'&nbsp;</td>';
+                  } else {
+                      $prevattempts.='<td>&nbsp;</td>';
+                  }
+              } else {
+                  my $value = &format_previous_attempt_value($key,$lasthash{$key});
+                  if ($key =~/$regexp$/ && (defined &$gradesub)) {
+                      $value = &$gradesub($value);
+                  }
+                  $prevattempts.='<td>'.$value.'&nbsp;</td>';
+              }
+          } else {
+	      my $value = &format_previous_attempt_value($key,$lasthash{$key});
+	      if ($key =~/$regexp$/ && (defined &$gradesub)) {
+                  $value = &$gradesub($value);
+              }
+	      $prevattempts.='<td>'.$value.'&nbsp;</td>';
+          }
       }
       $prevattempts.= &end_data_table_row().&end_data_table();
     } else {
@@ -3453,6 +3589,29 @@ sub format_previous_attempt_value {
 	$value = &Apache::lonlocal::locallocaltime($value);
     } elsif (ref($value) eq 'ARRAY') {
 	$value = '('.join(', ', @{ $value }).')';
+    } elsif ($key =~ /answerstring$/) {
+        my %answers = &Apache::lonnet::str2hash($value);
+        my @anskeys = sort(keys(%answers));
+        if (@anskeys == 1) {
+            my $answer = $answers{$anskeys[0]};
+            if ($answer =~ m{\0}) {
+                $answer =~ s{\0}{,}g;
+            }
+            my $tag_internal_answer_name = 'INTERNAL';
+            if ($anskeys[0] eq $tag_internal_answer_name) {
+                $value = $answer; 
+            } else {
+                $value = $anskeys[0].'='.$answer;
+            }
+        } else {
+            foreach my $ans (@anskeys) {
+                my $answer = $answers{$ans};
+                if ($answer =~ m{\0}) {
+                    $answer =~ s{\0}{,}g;
+                }
+                $value .=  $ans.'='.$answer.'<br />';;
+            } 
+        }
     } else {
 	$value = &unescape($value);
     }
@@ -3603,10 +3762,13 @@ sub submlink {
     }
     if (!$symb) { $symb=&Apache::lonnet::symbread(); }
     $symb=&escape($symb);
-    if ($target) { $target="target=\"$target\""; }
-    return '<a href="/adm/grades?&command=submission&'.
-	'symb='.$symb.'&student='.$uname.
-	'&userdom='.$udom.'" '.$target.'>'.$text.'</a>';
+    if ($target) { $target=" target=\"$target\""; }
+    return
+        '<a href="/adm/grades?command=submission'.
+        '&amp;symb='.$symb.
+        '&amp;student='.$uname.
+        '&amp;userdom='.$udom.'"'.
+        $target.'>'.$text.'</a>';
 }
 ##############################################
 
@@ -3728,10 +3890,13 @@ sub findallcourses {
         $udom = $env{'user.domain'};
     }
     if (($uname ne $env{'user.name'}) || ($udom ne $env{'user.domain'})) {
-        my %roleshash = &Apache::lonnet::dump('roles',$udom,$uname);
+        my $extra = &Apache::lonnet::freeze_escape({'skipcheck' => 1});
+        my %roleshash = &Apache::lonnet::dump('roles',$udom,$uname,'.',undef,
+                                              $extra);
         if (!%roles) {
             %roles = (
                        cc => 1,
+                       co => 1,
                        in => 1,
                        ep => 1,
                        ta => 1,
@@ -4132,16 +4297,39 @@ sub get_domainconf {
     if (defined($cached)) { return %{$result}; }
 
     my %domconfig = &Apache::lonnet::get_dom('configuration',
-					     ['login','rolecolors'],$udom);
+					     ['login','rolecolors','autoenroll'],$udom);
     my (%designhash,%legacy);
     if (keys(%domconfig) > 0) {
         if (ref($domconfig{'login'}) eq 'HASH') {
             if (keys(%{$domconfig{'login'}})) {
                 foreach my $key (keys(%{$domconfig{'login'}})) {
                     if (ref($domconfig{'login'}{$key}) eq 'HASH') {
-                        foreach my $img (keys(%{$domconfig{'login'}{$key}})) {
-                            $designhash{$udom.'.login.'.$key.'_'.$img} = 
-                                $domconfig{'login'}{$key}{$img};
+                        if ($key eq 'loginvia') {
+                            if (ref($domconfig{'login'}{'loginvia'}) eq 'HASH') {
+                                my @ids = &Apache::lonnet::current_machine_ids();
+                                foreach my $hostname (@ids) {
+                                    if (ref($domconfig{'login'}{'loginvia'}{$hostname}) eq 'HASH') {
+                                        if ($domconfig{'login'}{'loginvia'}{$hostname}{'server'}) {
+                                            my $server = $domconfig{'login'}{'loginvia'}{$hostname}{'server'};
+                                            $designhash{$udom.'.login.loginvia'} = $server;
+                                            if ($domconfig{'login'}{'loginvia'}{$hostname}{'serverpath'} eq 'custom') {
+
+                                                $designhash{$udom.'.login.loginvia_'.$hostname} = $server.':'.$domconfig{'login'}{'loginvia'}{$hostname}{'custompath'};
+                                            } else {
+                                                 $designhash{$udom.'.login.loginvia_'.$hostname} = $server.':'.$domconfig{'login'}{'loginvia'}{$hostname}{'serverpath'};
+                                            }
+                                            if ($domconfig{'login'}{'loginvia'}{$hostname}{'exempt'}) {
+                                                $designhash{$udom.'.login.loginvia_exempt_'.$hostname} = $domconfig{'login'}{'loginvia'}{$hostname}{'exempt'};
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        } else {
+                            foreach my $img (keys(%{$domconfig{'login'}{$key}})) {
+                                $designhash{$udom.'.login.'.$key.'_'.$img} = 
+                                    $domconfig{'login'}{$key}{$img};
+                            }
                         }
                     } else {
                         $designhash{$udom.'.login.'.$key}=$domconfig{'login'}{$key};
@@ -4168,6 +4356,11 @@ sub get_domainconf {
         } else {
             $legacy{'rolecolors'} = 1;
         }
+        if (ref($domconfig{'autoenroll'}) eq 'HASH') {
+            if ($domconfig{'autoenroll'}{'co-owners'}) {
+                $designhash{$udom.'.autoassign.co-owners'}=$domconfig{'autoenroll'}{'co-owners'};
+            }
+        }
         if (keys(%legacy) > 0) {
             my %legacyhash = &get_legacy_domconf($udom);
             foreach my $item (keys(%legacyhash)) {
@@ -4327,7 +4520,7 @@ Returns: HTML div with $content
 sub head_subbox {
     my ($content)=@_;
     my $output =
-        '<div id="LC_head_subbox">'
+        '<div class="LC_head_subbox">'
        .$content
        .'</div>'
 }
@@ -4360,18 +4553,30 @@ sub CSTR_pageheader {
     } else {
         $lastitem = $thisdisfn;
     }
-    return
+
+    my $output =
          '<div>'
         .&Apache::loncommon::help_open_menu('','',3,'Authoring') #FIXME: Broken? Where is it?
         .'<b>'.&mt('Construction Space:').'</b> '
         .'<form name="dirs" method="post" action="'.$formaction
-        .'" target="_top"><tt><b>' #FIXME lonpubdir: target="_parent"
-        .&Apache::lonhtmlcommon::crumbs($uname.'/'.$parentpath,'_top','/priv','','+1',1)."$lastitem</b></tt><br />"
+        .'" target="_top">' #FIXME lonpubdir: target="_parent"
+        .&Apache::lonhtmlcommon::crumbs($uname.'/'.$parentpath,'_top','/priv',undef,undef);
+
+    if ($lastitem) {
+        $output .=
+             '<span class="LC_filename">'
+            .$lastitem
+            .'</span>';
+    }
+    $output .=
+         '<br />'
         #FIXME lonpubdir: &Apache::lonhtmlcommon::crumbs($uname.$thisdisfn.'/','_top','/priv','','+1',1)."</b></tt><br />"
         .&Apache::lonhtmlcommon::select_recent('construct','recent','this.form.action=this.form.recent.value;this.form.submit()')
         .'</form>'
         .&Apache::lonmenu::constspaceform()
         .'</div>';
+
+    return $output;
 }
 
 ###############################################
@@ -4411,9 +4616,6 @@ Inputs:
 
 =item * $bgcolor, used to override the bgcolor on a webpage to a specific value
 
-=item * $no_inline_link, if true and in remote mode, don't show the 
-         'Switch To Inline Menu' link
-
 =item * $args, optional argument valid values are
             no_auto_mt_title -> prevents &mt()ing the title arg
             inherit_jsmath -> when creating popup window in a page,
@@ -4431,8 +4633,13 @@ other decorations will be returned.
 
 sub bodytag {
     my ($title,$function,$addentries,$bodyonly,$domain,$forcereg,
-        $no_nav_bar,$bgcolor,$no_inline_link,$args)=@_;
+        $no_nav_bar,$bgcolor,$args)=@_;
 
+    my $public;
+    if ((($env{'user.name'} eq 'public') && ($env{'user.domain'} eq 'public'))
+        || ($env{'user.name'} eq '') && ($env{'user.domain'} eq '')) {
+        $public = 1;
+    }
     if (!$args->{'no_auto_mt_title'}) { $title = &mt($title); }
 
     $function = &get_users_function() if (!$function);
@@ -4468,8 +4675,6 @@ sub bodytag {
     }
 
     if (!$realm) { $realm='&nbsp;'; }
-# Set messages
-    my $messages=&domainlogo($domain);
 
     my $extra_body_attr = &make_attr_string($forcereg,\%design);
 
@@ -4482,7 +4687,7 @@ sub bodytag {
     } 
 
     my $name = &plainname($env{'user.name'},$env{'user.domain'});
-    if ($env{'user.name'} eq 'public' && $env{'user.domain'} eq 'public') {
+    if ($public) {
 	undef($role);
     } else {
 	$name = &aboutmewrapper($name,$env{'user.name'},$env{'user.domain'});
@@ -4496,17 +4701,16 @@ sub bodytag {
                         $env{'course.'.$env{'request.course.id'}.
                                  '.domain'}.'/'})) {
         my $cid = $env{'request.course.id'};
-        $dc_info.= $cid.' '.$env{'course.'.$cid.'.internal.coursecode'};
+        $dc_info = $cid.' '.$env{'course.'.$cid.'.internal.coursecode'};
         $dc_info =~ s/\s+$//;
-        $dc_info = '('.$dc_info.')';
     }
 
     $role = '<span class="LC_nobreak">('.$role.')</span>' if $role;
     &get_unprocessed_cgi($ENV{'QUERY_STRING'}, ['inhibitmenu']);
 
-    if ($env{'environment.remote'} eq 'off') {
-        # No Remote
-        if ($no_nav_bar) { return $bodytag; } 
+        if ($no_nav_bar || $env{'form.inhibitmenu'} eq 'yes') { 
+            return $bodytag; 
+        } 
 
         if ($env{'request.state'} eq 'construct') { $forcereg=1; }
 
@@ -4514,27 +4718,42 @@ sub bodytag {
         #        $titleinfo = &CSTR_pageheader(); #FIXME: Will be removed once all scripts have their own calls
         #    }
 
-        $bodytag .= qq|<div id="LC_nav_bar">$name $role<br />
-            <em>$realm</em> $dc_info</div>| unless $env{'form.inhibitmenu'};
 
-        if (   $env{'form.inhibitmenu'} eq 'yes' 
-            || $ENV{'REQUEST_URI'} eq '/adm/logout'
-            || $env{'request.noversionuri'} =~ m{^/res/adm/pages/}) {
 
+        if ($env{'request.noversionuri'} =~ m{^/res/adm/pages/}) {
+             if ($dc_info) {
+                 $dc_info = qq|<span class="LC_cusr_subheading">$dc_info</span>|;
+             }
+             $bodytag .= qq|<div id="LC_nav_bar">$name $role<br />
+                <em>$realm</em> $dc_info</div>|;
             return $bodytag;
         }
 
+        unless ($env{'request.symb'} =~ m/\.page___\d+___/) {
+            $bodytag .= qq|<div id="LC_nav_bar">$name $role</div>|;
+        }
+
         $bodytag .= Apache::lonhtmlcommon::scripttag(
             Apache::lonmenu::utilityfunctions(), 'start');
 
         $bodytag .= Apache::lonmenu::primary_menu();
 
+        if ($dc_info) {
+            $dc_info = &dc_courseid_toggle($dc_info);
+        }
+        $bodytag .= qq|<div id="LC_realm">$realm $dc_info</div>|;
+
         #don't show menus for public users
-        if($env{'user.name'} ne 'public' && $env{'user.domain'} ne 'public'){
+        if (!$public){
             $bodytag .= Apache::lonmenu::secondary_menu();
             $bodytag .= Apache::lonmenu::serverform();
-            $bodytag .= Apache::lonhtmlcommon::scripttag('', 'end'); 
-            $bodytag .= Apache::lonmenu::innerregister($forcereg) if $forcereg;
+            $bodytag .= Apache::lonhtmlcommon::scripttag('', 'end');
+            if ($env{'request.state'} eq 'construct') {
+                $bodytag .= &Apache::lonmenu::innerregister($forcereg,
+                                $args->{'bread_crumbs'});
+            } elsif ($forcereg) { 
+                $bodytag .= &Apache::lonmenu::innerregister($forcereg);
+            }
         }else{
             # this is to seperate menu from content when there's no secondary
             # menu. Especially needed for public accessible ressources.
@@ -4542,40 +4761,15 @@ sub bodytag {
             $bodytag .= Apache::lonhtmlcommon::scripttag('', 'end'); 
         }
 
-        #SD testing
-        #$bodytag .= Apache::lonmenu::menubuttons($forcereg);
         return $bodytag;
-    }
-
-#
-# Top frame rendering, Remote is up
-#
+}
 
-    my $imgsrc = $img;
-    if ($img =~ /^\/adm/) {
-        $imgsrc = &lonhttpdurl($img);
-    }
-    my $upperleft='<img src="'.$imgsrc.'" alt="'.$function.'" />';
-
-    # Explicit link to get inline menu
-    my $menu= ($no_inline_link?''
-	       :'<a href="/adm/remote?action=collapse" target="_top">'.&mt('Switch to Inline Menu Mode').'</a>');
-    $bodytag .= qq|<div id="LC_nav_bar">$name $role
-            <em>$realm</em> $dc_info </div>
-            <ol class="LC_primary_menu LC_right">
-                <li>$menu</li>
-            </ol>| unless $env{'form.inhibitmenu'};
-    #
-    return(<<ENDBODY);
-$bodytag
-<table id="LC_title_bar" class="LC_with_remote">
-<tr><td>$upperleft</td>
-    <td>$messages&nbsp;</td>
-</tr>
-<tr><td>$titleinfo $dc_info $menu</td>
-</tr>
-</table>
-ENDBODY
+sub dc_courseid_toggle {
+    my ($dc_info) = @_;
+    return ' <span id="dccidtext" class="LC_cusr_subheading LC_nobreak">'.
+           '<a href="javascript:showCourseID();">'.
+           &mt('(More ...)').'</a></span>'.
+           '<div id="dccid" class="LC_dccid">'.$dc_info.'</div>';
 }
 
 sub make_attr_string {
@@ -4599,22 +4793,8 @@ sub make_attr_string {
 		delete($attr_ref->{$key});
 	    }
 	}
-	$attr_ref->{'onload'}  =
-	    &Apache::lonmenu::loadevents().  $on_load;
-	$attr_ref->{'onunload'}=
-	    &Apache::lonmenu::unloadevents().$on_unload;
-    }
-
-# Accessibility font enhance
-    if ($env{'browser.fontenhance'} eq 'on') {
-	my $style;
-	foreach my $key (keys(%{$attr_ref})) {
-	    if (lc($key) eq 'style') {
-		$style.=$attr_ref->{$key}.';';
-		delete($attr_ref->{$key});
-	    }
-	}
-	$attr_ref->{'style'}=$style.'; font-size: x-large;';
+	$attr_ref->{'onload'}  = $on_load;
+	$attr_ref->{'onunload'}= $on_unload;
     }
 
     my $attr_string;
@@ -4688,10 +4868,6 @@ sub standard_css {
     my $vlink  = &designparm($function.'.vlink', $domain);
     my $link   = &designparm($function.'.link',  $domain);
 
-    my $loginbg = &designparm('login.sidebg',$domain);
-    my $bgcol = &designparm('login.bgcol',$domain);
-    my $textcol = &designparm('login.textcol',$domain);
-
     my $sans                 = 'Verdana,Arial,Helvetica,sans-serif';
     my $mono                 = 'monospace';
     my $data_table_head      = $sidebg;
@@ -4709,49 +4885,70 @@ sub standard_css {
     my $mail_other_hover     = '#669999';
     my $table_header         = '#DDDDDD';
     my $feedback_link_bg     = '#BBBBBB';
-    my $lg_border_color	     = '#C8C8C8';
+    my $lg_border_color      = '#C8C8C8';
+    my $button_hover         = '#BF2317';
 
     my $border = ($env{'browser.type'} eq 'explorer' ||
-		  $env{'browser.type'} eq 'safari'     ) ? '0 2px 0 2px'
-	                                                 : '0 3px 0 4px';
+      $env{'browser.type'} eq 'safari'     ) ? '0 2px 0 2px'
+                                             : '0 3px 0 4px';
 
 
     return <<END;
-body {
-   font-family: $sans;
-   line-height:130%;
-   font-size:0.83em;
-   color:$font;
+
+/* needed for iframe to allow 100% height in FF */
+body, html { 
+    margin: 0;
+    padding: 0 0.5%;
+    height: 99%; /* to avoid scrollbars */
 }
 
-a:link, a:visited { 
-  font-size:100%; 
+body {
+  font-family: $sans;
+  line-height:130%;
+  font-size:0.83em;
+  color:$font;
 }
 
-a:focus { 
+a:focus,
+a:focus img {
   color: red;
-  background: yellow 
+  background: yellow;
 }
 
-form, .inline { 
-   display: inline; 
+form, .inline {
+  display: inline;
 }
 
 .LC_right {
-   text-align:right;
+  text-align:right;
 }
 
 .LC_middle {
-   vertical-align:middle;
+  vertical-align:middle;
 }
 
-/* just for tests */
-.LC_400Box {width:400px; }
-/* end */
+.LC_400Box {
+  width:400px;
+}
+
+.LC_iframecontainer {
+    width: 98%;
+    margin: 0;
+    position: fixed;
+    top: 8.5em;
+    bottom: 0;
+}
+
+.LC_iframecontainer iframe{
+    border: none;
+    width: 100%;
+    height: 100%;
+}
 
 .LC_filename {
   font-family: $mono;
   white-space:pre;
+  font-size: 120%;
 }
 
 .LC_fileicon {
@@ -4762,6 +4959,10 @@ form, .inline {
   text-decoration:none;
 }
 
+.LC_setting {
+  text-decoration:underline;
+}
+
 .LC_error {
   color: red;
   font-size: larger;
@@ -4806,35 +5007,35 @@ div.LC_confirm_box .LC_success img {
 }
 
 .LC_discussion {
-   background: $tabbg;
-   border: 1px solid black;
-   margin: 2px;
+  background: $tabbg;
+  border: 1px solid black;
+  margin: 2px;
 }
 
 .LC_disc_action_links_bar {
-   background: $tabbg;
-   border: none;
-   margin: 4px;
+  background: $tabbg;
+  border: none;
+  margin: 4px;
 }
 
 .LC_disc_action_left {
-   text-align: left;
+  text-align: left;
 }
 
 .LC_disc_action_right {
-   text-align: right;
+  text-align: right;
 }
 
 .LC_disc_new_item {
-   background: white;
-   border: 2px solid red;
-   margin: 2px;
+  background: white;
+  border: 2px solid red;
+  margin: 2px;
 }
 
 .LC_disc_old_item {
-   background: white;
-   border: 1px solid black;
-   margin: 2px;
+  background: white;
+  border: 1px solid black;
+  margin: 2px;
 }
 
 table.LC_pastsubmission {
@@ -4842,9 +5043,7 @@ table.LC_pastsubmission {
   margin: 2px;
 }
 
-table#LC_top_nav,
-table#LC_menubuttons,
-table#LC_nav_location {
+table#LC_menubuttons {
   width: 100%;
   background: $pgbg;
   border: 2px;
@@ -4862,7 +5061,7 @@ table#LC_title_bar {
 }
 
 table#LC_title_bar,
-table.LC_breadcrumbs,
+table.LC_breadcrumbs, /* obsolete? */
 table#LC_title_bar.LC_with_remote {
   width: 100%;
   border-color: $pgbg;
@@ -4875,100 +5074,77 @@ table#LC_title_bar.LC_with_remote {
   margin: 0;
 }
 
-table#LC_title_bar td {
-  background: $tabbg;
+ul.LC_breadcrumb_tools_outerlist {
+    margin: 0;
+    padding: 0;
+    position: relative;
+    list-style: none;
 }
-
-table#LC_menubuttons img{
-  border: none;
+ul.LC_breadcrumb_tools_outerlist li {
+    display: inline;
 }
 
-table#LC_top_nav td {
-  background: $tabbg;
-  border: none;
-  font-size: small;
-  vertical-align:top;
-  padding:2px 5px 2px 5px;
+.LC_breadcrumb_tools_navigation {
+    padding: 0;
+    margin: 0;
+    float: left;
 }
-
-table#LC_top_nav td a,
-div#LC_top_nav a {
-  color: $font;
+.LC_breadcrumb_tools_tools {
+    padding: 0;
+    margin: 0;
+    float: right;
 }
 
-table#LC_top_nav td.LC_top_nav_logo {
+table#LC_title_bar td {
   background: $tabbg;
-  text-align: left;
-  white-space: nowrap;
-  width: 31px;
 }
 
-table#LC_top_nav td.LC_top_nav_logo img {
+table#LC_menubuttons img {
   border: none;
-  vertical-align: bottom;
-}
-
-table#LC_top_nav td.LC_top_nav_exit,
-table#LC_top_nav td.LC_top_nav_help {
-  width: 2.0em;
-}
-
-table#LC_top_nav td.LC_top_nav_login {
-  width: 4.0em;
-  text-align: center;
 }
 
 .LC_breadcrumbs_component {
-    float: right;
-    margin: 0 1em;
+  float: right;
+  margin: 0 1em;
 }
 .LC_breadcrumbs_component img {
-    vertical-align: middle;
+  vertical-align: middle;
 }
 
 td.LC_table_cell_checkbox {
   text-align: center;
 }
 
-table#LC_mainmenu td.LC_mainmenu_column {
-    vertical-align: top;
-}
-
 .LC_fontsize_small {
- font-size: 70%;
+  font-size: 70%;
 }
 
 #LC_breadcrumbs {
- clear:both;
- background: $sidebg;
- border-bottom: 1px solid $lg_border_color;
- line-height: 2.5em; 
- /* SD working here
- height: 2.5em;
- overflow: hidden; */
- margin: 0;
- padding: 0;
-}
-
-/* Preliminary fix to hide breadcrumbs inside remote control window */
-#LC_remote #LC_breadcrumbs {
-    display:none;
-}
-
-#LC_head_subbox {
- clear:both;
- background: #F8F8F8; /* $sidebg; */
- border-bottom: 1px solid $lg_border_color;
- margin: 0 0 10px 0;
- padding: 5px;
+  clear:both;
+  background: $sidebg;
+  border-bottom: 1px solid $lg_border_color;
+  line-height: 2.5em;
+  overflow: hidden;
+  margin: 0;
+  padding: 0;
+  text-align: left;
+}
+
+.LC_head_subbox {
+  clear:both;
+  background: #F8F8F8; /* $sidebg; */
+  border: 1px solid $sidebg;
+  margin: 0 0 10px 0;      
+  padding: 3px;
+  text-align: left;
 }
 
 .LC_fontsize_medium {
- font-size: 85%;
+  font-size: 85%;
 }
 
 .LC_fontsize_large {
- font-size: 120%;
+  font-size: 120%;
 }
 
 .LC_menubuttons_inline_text {
@@ -4977,6 +5153,15 @@ table#LC_mainmenu td.LC_mainmenu_column
   padding-left:3px;
 }
 
+.LC_menubuttons_inline_text img{
+  vertical-align: middle;
+}
+
+li.LC_menubuttons_inline_text img,a {
+  cursor:pointer;
+  text-decoration: none;
+}
+
 .LC_menubuttons_link {
   text-decoration: none;
 }
@@ -4989,20 +5174,14 @@ table#LC_mainmenu td.LC_mainmenu_column
 }
 
 td.LC_menubuttons_text {
- 	color: $font;
+  color: $font;
 }
 
 .LC_current_location {
   background: $tabbg;
 }
 
-.LC_new_mail {
-  background: $tabbg;
-  font-weight: bold;
-}
-
-table.LC_data_table,
-table.LC_mail_list {
+table.LC_data_table {
   border: 1px solid #000000;
   border-collapse: separate;
   border-spacing: 1px;
@@ -5028,9 +5207,8 @@ table.LC_nested {
   width: 100%;
 }
 
-table.LC_data_table tr th, 
-table.LC_calendar tr th, 
-table.LC_mail_list tr th,
+table.LC_data_table tr th,
+table.LC_calendar tr th,
 table.LC_prior_tries tr th,
 table.LC_innerpickbox tr th {
   font-weight: bold;
@@ -5050,17 +5228,25 @@ table.LC_data_table tr.LC_info_row > td
   text-align: left;
 }
 
-table.LC_data_table tr.LC_odd_row > td,
+table.LC_data_table tr.LC_odd_row > td {
+  background-color: $data_table_light;
+  padding: 2px;
+  vertical-align: top;
+}
+
 table.LC_pick_box tr > td.LC_odd_row {
   background-color: $data_table_light;
+  vertical-align: top;
+}
+
+table.LC_data_table tr.LC_even_row > td {
+  background-color: $data_table_dark;
   padding: 2px;
   vertical-align: top;
 }
 
-table.LC_data_table tr.LC_even_row > td,
 table.LC_pick_box tr > td.LC_even_row {
   background-color: $data_table_dark;
-  padding: 2px;
   vertical-align: top;
 }
 
@@ -5075,13 +5261,20 @@ table.LC_data_table tr td.LC_leftcol_hea
 
 table.LC_data_table tr.LC_empty_row td,
 table.LC_nested tr.LC_empty_row td {
-  background-color: #FFFFFF;
   font-weight: bold;
   font-style: italic;
   text-align: center;
   padding: 8px;
 }
 
+table.LC_data_table tr.LC_empty_row td {
+  background-color: $sidebg;
+}
+
+table.LC_nested tr.LC_empty_row td {
+  background-color: #FFFFFF;
+}
+
 table.LC_caption {
 }
 
@@ -5149,6 +5342,7 @@ table.LC_createuser tr.LC_info_row td  {
 table.LC_calendar {
   border: 1px solid #000000;
   border-collapse: collapse;
+  width: 98%;
 }
 
 table.LC_calendar_pickdate {
@@ -5158,6 +5352,7 @@ table.LC_calendar_pickdate {
 table.LC_calendar tr td {
   border: 1px solid #000000;
   vertical-align: top;
+  width: 14%;
 }
 
 table.LC_calendar tr td.LC_calendar_day_empty {
@@ -5168,43 +5363,43 @@ table.LC_calendar tr td.LC_calendar_day_
   background-color: $data_table_highlight;
 }
 
-table.LC_mail_list tr.LC_mail_new {
+table.LC_data_table tr td.LC_mail_new {
   background-color: $mail_new;
 }
 
-table.LC_mail_list tr.LC_mail_new:hover {
+table.LC_data_table tr.LC_mail_new:hover {
   background-color: $mail_new_hover;
 }
 
-table.LC_mail_list tr.LC_mail_even {
-}
-
-table.LC_mail_list tr.LC_mail_odd {
-}
-
-table.LC_mail_list tr.LC_mail_read {
+table.LC_data_table tr td.LC_mail_read {
   background-color: $mail_read;
 }
 
-table.LC_mail_list tr.LC_mail_read:hover {
+/*
+table.LC_data_table tr.LC_mail_read:hover {
   background-color: $mail_read_hover;
 }
+*/
 
-table.LC_mail_list tr.LC_mail_replied {
+table.LC_data_table tr td.LC_mail_replied {
   background-color: $mail_replied;
 }
 
-table.LC_mail_list tr.LC_mail_replied:hover {
+/*
+table.LC_data_table tr.LC_mail_replied:hover {
   background-color: $mail_replied_hover;
 }
+*/
 
-table.LC_mail_list tr.LC_mail_other {
+table.LC_data_table tr td.LC_mail_other {
   background-color: $mail_other;
 }
 
-table.LC_mail_list tr.LC_mail_other:hover {
+/*
+table.LC_data_table tr.LC_mail_other:hover {
   background-color: $mail_other_hover;
 }
+*/
 
 table.LC_data_table tr > td.LC_browser_file,
 table.LC_data_table tr > td.LC_browser_file_published {
@@ -5230,27 +5425,27 @@ table.LC_data_table tr.LC_browser_folder
 }
 
 table.LC_data_table tr > td.LC_roles_is {
-/*  background: #77FF77; */
+  /* background: #77FF77; */
 }
 
 table.LC_data_table tr > td.LC_roles_future {
-  background: #FFFF77;
+  border-right: 8px solid #FFFF77;
 }
 
 table.LC_data_table tr > td.LC_roles_will {
-  background: #FFAA77;
+  border-right: 8px solid #FFAA77;
 }
 
 table.LC_data_table tr > td.LC_roles_expired {
-  background: #FF7777;
+  border-right: 8px solid #FF7777;
 }
 
 table.LC_data_table tr > td.LC_roles_will_not {
-  background: #AAFF77;
+  border-right: 8px solid #AAFF77;
 }
 
 table.LC_data_table tr > td.LC_roles_selected {
-  background: #11CC55;
+  border-right: 8px solid #11CC55;
 }
 
 span.LC_current_location {
@@ -5278,12 +5473,21 @@ span.LC_parm_part {
   color: blue;
 }
 
-span.LC_parm_folder, span.LC_parm_symb {
+span.LC_parm_folder,
+span.LC_parm_symb {
   font-size: x-small;
   font-family: $mono;
   color: #AAAAAA;
 }
 
+ul.LC_parm_parmlist li {
+  display: inline-block;
+  padding: 0.3em 0.8em;
+  vertical-align: top;
+  width: 150px;
+  border-top:1px solid $lg_border_color;
+}
+
 td.LC_parm_overview_level_menu,
 td.LC_parm_overview_map_menu,
 td.LC_parm_overview_parm_selectors,
@@ -5444,35 +5648,23 @@ table.LC_group_priv td {
   padding: 0;
 }
 
-table.LC_notify_front_page {
-  background: white;
-  border: 1px solid black;
-  padding: 8px;
-}
-
-table.LC_notify_front_page td {
-  padding: 8px;
-}
-
 .LC_navbuttons {
   margin: 2ex 0ex 2ex 0ex;
 }
 
 .LC_topic_bar {
   font-weight: bold;
-  width: 100%;
   background: $tabbg;
-  vertical-align: middle;
-  margin: 2ex 0ex 2ex 0ex;
+  margin: 1em 0em 1em 2em;
   padding: 3px;
+  font-size: 1.2em;
 }
 
 .LC_topic_bar span {
+  left: 0.5em;
+  position: absolute;
   vertical-align: middle;
-}
-
-.LC_topic_bar img {
-  vertical-align: bottom;
+  font-size: 1.2em;
 }
 
 table.LC_course_group_status {
@@ -5501,12 +5693,12 @@ div.LC_feedback_link img {
   vertical-align:middle;
 }
 
-div.LC_feedback_link a{
+div.LC_feedback_link a {
   text-decoration: none;
 }
 
 div.LC_comblock {
-  display:inline; 
+  display:inline;
   color:$font;
   font-size:90%;
 }
@@ -5584,12 +5776,12 @@ span.LC_prior_string,
 span.LC_prior_custom,
 span.LC_prior_reaction,
 span.LC_prior_math {
-  font-family: monospace;
+  font-family: $mono;
   white-space: pre;
 }
 
 span.LC_prior_string {
-  font-family: monospace;
+  font-family: $mono;
   white-space: pre;
 }
 
@@ -5598,7 +5790,7 @@ table.LC_prior_option {
   border-collapse: collapse;
 }
 
-table.LC_prior_rank, 
+table.LC_prior_rank,
 table.LC_prior_match {
   border-collapse: collapse;
 }
@@ -5622,17 +5814,6 @@ span.LC_cusr_subheading {
   font-size: 85%;
 }
 
-table.LC_docs_documents {
-  background: #BBBBBB;
-  border-width: 0;
-  border-collapse: collapse;
-}
-
-table.LC_docs_documents td.LC_docs_document {
-  border: 2px solid black;
-  padding: 4px;
-}
-
 div.LC_docs_entry_move {
   border: 1px solid #BBBBBB;
   background: #DDDDDD;
@@ -5724,56 +5905,41 @@ div.LC_clear_float_footer {
 }
 
 div.LC_grade_show_user {
-  margin-top: 20px;
-  border: 1px solid black;
+/*  border-left: 5px solid $sidebg; */
+  border-top: 5px solid #000000;
+  margin: 50px 0 0 0;
+  padding: 15px 0 5px 10px;
 }
 
-div.LC_grade_user_name {
-  background: #DDDDEE;
-  border-bottom: 1px solid black;
-  font-weight: bold;
-  font-size: large;
+div.LC_grade_show_user_odd_row {
+/*  border-left: 5px solid #000000; */
 }
 
-div.LC_grade_show_user_odd_row div.LC_grade_user_name {
-  background: #DDEEDD;
+div.LC_grade_show_user div.LC_Box {
+  margin-right: 50px;
 }
 
-div.LC_grade_show_problem,
 div.LC_grade_submissions,
 div.LC_grade_message_center,
-div.LC_grade_info_links,
-div.LC_grade_assign {
+div.LC_grade_info_links {
   margin: 5px;
   width: 99%;
   background: #FFFFFF;
 }
 
-div.LC_grade_show_problem_header,
 div.LC_grade_submissions_header,
-div.LC_grade_message_center_header,
-div.LC_grade_assign_header {
+div.LC_grade_message_center_header {
   font-weight: bold;
   font-size: large;
 }
 
-div.LC_grade_show_problem_problem,
 div.LC_grade_submissions_body,
-div.LC_grade_message_center_body,
-div.LC_grade_assign_body {
+div.LC_grade_message_center_body {
   border: 1px solid black;
   width: 99%;
   background: #FFFFFF;
 }
 
-span.LC_grade_check_note {
-  font-weight: normal;
-  font-size: medium;
-  display: inline;
-  position: absolute;
-  right: 1em;
-}
-
 table.LC_scantron_action {
   width: 100%;
 }
@@ -5807,15 +5973,8 @@ div.LC_edit_problem_header_title {
 }
 
 table.LC_edit_problem_header_title {
-  font-size: larger;
-  font-weight:  bold;
   width: 100%;
-  border-color: $pgbg;
-  border-style: solid;
-  border-width: $border;
   background: $tabbg;
-  border-collapse: collapse;
-  padding: 0;
 }
 
 div.LC_edit_problem_discards {
@@ -5828,38 +5987,25 @@ div.LC_edit_problem_saves {
   padding-bottom: 5px;
 }
 
-img.stift{
+img.stift {
   border-width: 0;
   vertical-align: middle;
 }
 
-table#LC_mainmenu{
- margin-top:10px;
- width:80%;
-}
-
-table#LC_mainmenu td.LC_mainmenu_col_fieldset{
+table td.LC_mainmenu_col_fieldset {
   vertical-align: top;
-  width: 45%;
-}
-
-.LC_mainmenu_fieldset_category {
-  color: $font;
-  background: $pgbg;
-  font-size: small;
-  font-weight: bold;
 }
 
 div.LC_createcourse {
-    margin: 10px 10px 10px 10px;
+  margin: 10px 10px 10px 10px;
 }
 
-/* ---- Remove when done ----
-# The following styles is part of the redesign of LON-CAPA and are
-# subject to change during this project.
-# Don't rely on their current functionality as they might be 
-# changed or removed.
-# --------------------------*/
+.LC_dccid {
+  margin: 0.2em 0 0 0;
+  padding: 0;
+  font-size: 90%;
+  display:none;
+}
 
 a:hover,
 ol.LC_primary_menu a:hover,
@@ -5868,220 +6014,287 @@ ol#LC_PathBreadcrumbs a:hover,
 ul#LC_secondary_menu a:hover,
 .LC_FormSectionClearButton input:hover
 ul.LC_TabContent   li:hover a {
-	color:#BF2317;
-    text-decoration:none;
+  color:$button_hover;
+  text-decoration:none;
 }
 
 h1 {
-	padding: 0;
-	line-height:130%;
+  padding: 0;
+  line-height:130%;
 }
 
-h2,h3,h4,h5,h6 {
-	margin: 5px 0 5px 0;
-	padding: 0;
-	line-height:130%;
+h2,
+h3,
+h4,
+h5,
+h6 {
+  margin: 5px 0 5px 0;
+  padding: 0;
+  line-height:130%;
 }
 
 .LC_hcell {
-        padding:3px 15px 3px 15px;
-        margin: 0;
-	background-color:$tabbg;
-	color:$fontmenu;
-	border-bottom:solid 1px $lg_border_color;
+  padding:3px 15px 3px 15px;
+  margin: 0;
+  background-color:$tabbg;
+  color:$fontmenu;
+  border-bottom:solid 1px $lg_border_color;
 }
 
 .LC_Box > .LC_hcell {
-    margin: 0 -10px 10px -10px;
+  margin: 0 -10px 10px -10px;
 }
 
 .LC_noBorder {
-        border: 0;
-}
-
-.LC_Right {
-        float: right;
-        margin: 0;
-        padding: 0;
+  border: 0;
 }
 
 .LC_FormSectionClearButton input {
-        background-color:transparent;
-        border: none;
-        cursor:pointer;
-        text-decoration:underline;
+  background-color:transparent;
+  border: none;
+  cursor:pointer;
+  text-decoration:underline;
 }
 
 .LC_help_open_topic {
-        color: #FFFFFF;
-        background-color: #EEEEFF;
-        margin: 1px;
-        padding: 4px;
-        border: 1px solid #000033;
-        white-space: nowrap;
-/*		vertical-align: middle; */
+  color: #FFFFFF;
+  background-color: #EEEEFF;
+  margin: 1px;
+  padding: 4px;
+  border: 1px solid #000033;
+  white-space: nowrap;
+  /* vertical-align: middle; */
 }
 
-dl,ul,div,fieldset {
-	margin: 10px 10px 10px 0;
-/*	overflow: hidden; */
+dl,
+ul,
+div,
+fieldset {
+  margin: 10px 10px 10px 0;
+  /* overflow: hidden; */
 }
 
 fieldset > legend {
-    font-weight: bold;
-    padding: 0 5px 0 5px;
+  font-weight: bold;
+  padding: 0 5px 0 5px;
 }
 
 #LC_nav_bar {
-    float: left;
-    margin: 0.2em 0 0 0;
+  float: left;
+  background-color: $pgbg_or_bgcolor;
+  margin: 0 0 2px 0;
+}
+
+#LC_realm {
+  margin: 0.2em 0 0 0;
+  padding: 0;
+  font-weight: bold;
+  text-align: center;
+  background-color: $pgbg_or_bgcolor;
 }
 
-#LC_nav_bar em{
-    font-weight: bold;
-    font-style: normal;
+#LC_nav_bar em {
+  font-weight: bold;
+  font-style: normal;
 }
 
 ol.LC_primary_menu {
-    float: right;
-    margin: 0.2em 0 0 0;
+  float: right;
+  margin: 0;
+  background-color: $pgbg_or_bgcolor;
 }
 
 ol#LC_PathBreadcrumbs {
-	margin: 0;
+  margin: 0;
 }
 
 ol.LC_primary_menu li {
-	display: inline;
-	padding: 5px 5px 0 10px;
-	vertical-align: top;
+  display: inline;
+  padding: 5px 5px 0 10px;
+  vertical-align: top;
 }
 
 ol.LC_primary_menu li img {
-	vertical-align: bottom;
+  vertical-align: bottom;
+  height: 1.1em;
 }
 
 ol.LC_primary_menu a {
-	font-size: 90%;
-	color: RGB(80, 80, 80);
-	text-decoration: none;
+  color: RGB(80, 80, 80);
+  text-decoration: none;
+}
+
+ol.LC_primary_menu a.LC_new_message {
+  font-weight:bold;
+  color: darkred;
+}
+
+ol.LC_docs_parameters {
+  margin-left: 0;
+  padding: 0;
+  list-style: none;
+}
+
+ol.LC_docs_parameters li {
+  margin: 0;
+  padding-right: 20px;
+  display: inline;
+}
+
+ol.LC_docs_parameters li:before {
+  content: "\\002022 \\0020";
+}
+
+li.LC_docs_parameters_title {
+  font-weight: bold;
+}
+
+ol.LC_docs_parameters li.LC_docs_parameters_title:before {
+  content: "";
 }
 
 ul#LC_secondary_menu {
-    clear: both;
-    color: $fontmenu;
-    background: $tabbg;
-    list-style: none;
-    padding: 0;
-    margin: 0;
-    width: 100%;
+  clear: both;
+  color: $fontmenu;
+  background: $tabbg;
+  list-style: none;
+  padding: 0;
+  margin: 0;
+  width: 100%;
+  text-align: left;
 }
 
 ul#LC_secondary_menu li {
-    font-weight: bold;
-    line-height: 1.8em;
-    padding: 0 0.8em; 
-    border-right: 1px solid black;
-    display: inline;
-    vertical-align: middle;
+  font-weight: bold;
+  line-height: 1.8em;
+  padding: 0 0.8em;
+  border-right: 1px solid black;
+  display: inline;
+  vertical-align: middle;
 }
 
 ul.LC_TabContent {
-	display:block;
-	background: $sidebg;
-	border-bottom: solid 1px $lg_border_color;
-	list-style:none;
-	margin: 0 -10px;
-	padding: 0;
+  display:block;
+  background: $sidebg;
+  border-bottom: solid 1px $lg_border_color;
+  list-style:none;
+  margin: 0 -10px;
+  padding: 0;
 }
 
 ul.LC_TabContent li,
 ul.LC_TabContentBigger li {
-	float:left;
+  float:left;
 }
 
 ul#LC_secondary_menu li a {
-    color: $fontmenu;
-	text-decoration: none;
+  color: $fontmenu;
+  text-decoration: none;
 }
 
 ul.LC_TabContent {
-	min-height:1.5em;
+  min-height:20px;
 }
 
 ul.LC_TabContent li {
-	vertical-align:middle;
-	padding: 0 10px 0 10px;
-	background-color:$tabbg;
-	border-bottom:solid 1px $lg_border_color;
+  vertical-align:middle;
+  padding: 0 16px 0 10px;
+  background-color:$tabbg;
+  border-bottom:solid 1px $lg_border_color;
+  border-right: solid 1px $font;
 }
 
 ul.LC_TabContent .right {
-	float:right;
+  float:right;
 }
 
-ul.LC_TabContent li a, ul.LC_TabContent li {
-	color:rgb(47,47,47);
-	text-decoration:none;
-	font-size:95%;
-	font-weight:bold;
-	padding-right: 16px;
+ul.LC_TabContent li a,
+ul.LC_TabContent li {
+  color:rgb(47,47,47);
+  text-decoration:none;
+  font-size:95%;
+  font-weight:bold;
+  min-height:20px;
 }
 
-ul.LC_TabContent li:hover, ul.LC_TabContent li.active {
-        background:#FFFFFF url(/adm/lonIcons/open.gif) no-repeat scroll right center;
-	border-bottom:solid 2px #FFFFFF;
-	padding-right: 16px;
+ul.LC_TabContent li a:hover,
+ul.LC_TabContent li a:focus {
+  color: $button_hover;
+  background:none;
+  outline:none;
 }
 
+ul.LC_TabContent li:hover {
+  color: $button_hover;
+  cursor:pointer;
+}
+
+ul.LC_TabContent li.active {
+  color: $font;
+  background:#FFFFFF url(/adm/lonIcons/open.gif) no-repeat scroll right center;
+  border-bottom:solid 1px #FFFFFF;
+  cursor: default;
+}
+
+ul.LC_TabContent li.active a {
+  color:$font;
+  background:#FFFFFF;
+  outline: none;
+}
 #maincoursedoc {
-	clear:both;
+  clear:both;
 }
 
 ul.LC_TabContentBigger {
-        display:block;
-        list-style:none;
-        padding: 0;
+  display:block;
+  list-style:none;
+  padding: 0;
 }
 
 ul.LC_TabContentBigger li {
-        vertical-align:bottom;
-        height: 30px;
-        font-size:110%;
-        font-weight:bold;
-        color: #737373;
+  vertical-align:bottom;
+  height: 30px;
+  font-size:110%;
+  font-weight:bold;
+  color: #737373;
 }
 
+ul.LC_TabContentBigger li.active {
+  position: relative;
+  top: 1px;
+}
 
 ul.LC_TabContentBigger li a {
-        background:url('/adm/lonIcons/tabbgleft.gif') left bottom no-repeat;
-	height: 30px;
-	line-height: 30px;
-	text-align: center;
-	display: block;
-	text-decoration: none;
+  background:url('/adm/lonIcons/tabbgleft.gif') left bottom no-repeat;
+  height: 30px;
+  line-height: 30px;
+  text-align: center;
+  display: block;
+  text-decoration: none;
+  outline: none;  
 }
 
-ul.LC_TabContentBigger li:hover a, 
 ul.LC_TabContentBigger li.active a {
-	background:url('/adm/lonIcons/tabbgleft.gif') left top no-repeat;
-	color:$font;
-	text-decoration: underline;
+  background:url('/adm/lonIcons/tabbgleft.gif') left top no-repeat;
+  color:$font;
 }
 
-
 ul.LC_TabContentBigger li b {
-	background: url('/adm/lonIcons/tabbgright.gif') no-repeat right bottom;
-	display: block;
-	float: left;
-	padding: 0 30px;
+  background: url('/adm/lonIcons/tabbgright.gif') no-repeat right bottom;
+  display: block;
+  float: left;
+  padding: 0 30px;
+  border-bottom: 1px solid $lg_border_color;
+}
+
+ul.LC_TabContentBigger li:hover b {
+  color:$button_hover;
 }
 
-ul.LC_TabContentBigger li:hover b,
 ul.LC_TabContentBigger li.active b {
-        background:url('/adm/lonIcons/tabbgright.gif') right top no-repeat;
-        color:$font;
-	border-bottom: 1px solid #FFFFFF;
+  background:url('/adm/lonIcons/tabbgright.gif') right top no-repeat;
+  color:$font;
+  border: 0;
 }
 
 
@@ -6094,69 +6307,72 @@ ul.LC_CourseBreadcrumbs {
 
 }
 
-ol#LC_MenuBreadcrumbs, 
+ol#LC_MenuBreadcrumbs,
 ol#LC_PathBreadcrumbs {
-	padding-left: 10px;
-	margin: 0;
-	list-style-position: inside;
-    /* SD working here
-    white-space: nowrap; */
+  padding-left: 10px;
+  margin: 0;
+  height: 2.5em;  /* equal to #LC_breadcrumbs line-height */
 }
 
-ol#LC_MenuBreadcrumbs li, 
-ol#LC_PathBreadcrumbs li, 
+ol#LC_MenuBreadcrumbs li,
+ol#LC_PathBreadcrumbs li,
 ul.LC_CourseBreadcrumbs li {
-    display: inline;
-    white-space: nowrap;
-    /* SD working here
-    white-space: normal; */
+  display: inline;
+  white-space: normal;  
 }
 
 ol#LC_MenuBreadcrumbs li a,
 ul.LC_CourseBreadcrumbs li a {
-	text-decoration: none;
-	font-size:90%;
+  text-decoration: none;
+  font-size:90%;
+}
+
+ol#LC_MenuBreadcrumbs h1 {
+  display: inline;
+  font-size: 90%;
+  line-height: 2.5em;
+  margin: 0;
+  padding: 0;
 }
 
 ol#LC_PathBreadcrumbs li a {
-	text-decoration:none;
-	font-size:100%;
-	font-weight:bold;
+  text-decoration:none;
+  font-size:100%;
+  font-weight:bold;
 }
 
 .LC_Box {
-    border: solid 1px $lg_border_color;
-    padding: 0 10px 10px 10px;
+  border: solid 1px $lg_border_color;
+  padding: 0 10px 10px 10px;
 }
 
 .LC_AboutMe_Image {
-	float:left;
-	margin-right:10px;
+  float:left;
+  margin-right:10px;
 }
 
 .LC_Clear_AboutMe_Image {
-	clear:left;
+  clear:left;
 }
 
 dl.LC_ListStyleClean dt {
-	padding-right: 5px;
-	display: table-header-group;
+  padding-right: 5px;
+  display: table-header-group;
 }
 
 dl.LC_ListStyleClean dd {
-	display: table-row;
+  display: table-row;
 }
 
 .LC_ListStyleClean,
 .LC_ListStyleSimple,
 .LC_ListStyleNormal,
-.LC_ListStyle_Border,
 .LC_ListStyleSpecial {
-	/*display:block;	*/
-	list-style-position: inside;
-	list-style-type: none;
-	overflow: hidden;
-	padding: 0;
+  /* display:block; */
+  list-style-position: inside;
+  list-style-type: none;
+  overflow: hidden;
+  padding: 0;
 }
 
 .LC_ListStyleSimple li,
@@ -6165,211 +6381,178 @@ dl.LC_ListStyleClean dd {
 .LC_ListStyleNormal dd,
 .LC_ListStyleSpecial li,
 .LC_ListStyleSpecial dd {
-	margin: 0;
-	padding: 5px 5px 5px 10px;
-	clear: both;
+  margin: 0;
+  padding: 5px 5px 5px 10px;
+  clear: both;
 }
 
 .LC_ListStyleClean li,
 .LC_ListStyleClean dd {
-	padding-top: 0;
-	padding-bottom: 0;
+  padding-top: 0;
+  padding-bottom: 0;
 }
 
 .LC_ListStyleSimple dd,
 .LC_ListStyleSimple li {
-	border-bottom: solid 1px $lg_border_color;
+  border-bottom: solid 1px $lg_border_color;
 }
 
 .LC_ListStyleSpecial li,
 .LC_ListStyleSpecial dd {
-	list-style-type: none;
-	background-color: RGB(220, 220, 220);
-	margin-bottom: 4px;
+  list-style-type: none;
+  background-color: RGB(220, 220, 220);
+  margin-bottom: 4px;
 }
 
 table.LC_SimpleTable {
-	margin:5px;
-	border:solid 1px $lg_border_color;
+  margin:5px;
+  border:solid 1px $lg_border_color;
 }
 
 table.LC_SimpleTable tr {
-	padding: 0;
-	border:solid 1px $lg_border_color;
+  padding: 0;
+  border:solid 1px $lg_border_color;
 }
 
 table.LC_SimpleTable thead {
-	 background:rgb(220,220,220);
+  background:rgb(220,220,220);
 }
 
 div.LC_columnSection {
-	display: block;
-	clear: both;
-	overflow: hidden;
-	margin: 0;
+  display: block;
+  clear: both;
+  overflow: hidden;
+  margin: 0;
 }
 
 div.LC_columnSection>* {
-	float: left;
-	margin: 10px 20px 10px 0;
-	overflow:hidden;
-}
-
-.LC_loginpage_container {
-	text-align:left;
-	margin : 0 auto;
-	width:90%;
-	padding: 10px;
-	height: auto;
-	background-color:#FFFFFF;
-	border:1px solid #CCCCCC;
-}
-
-
-.LC_loginpage_loginContainer {
-	float:left;
-	width: 182px;
-	padding: 2px;
-	border:1px solid #CCCCCC;
-	background-color:$loginbg;
-}
-
-.LC_loginpage_loginContainer h2 {
-	margin-top: 0;
-	display:block;
-	background:$bgcol;
-	color:$textcol;
-	padding-left:5px;
-}
-
-.LC_loginpage_loginInfo {
-	float:left;
-	width:182px;
-	border:1px solid #CCCCCC;
-	padding:2px;
-}
-
-.LC_loginpage_space {
-	clear: both;
-	margin-bottom: 20px;
-	border-bottom: 1px solid #CCCCCC;
-}
-
-.LC_loginpage_floatLeft {
-	float: left;
-	width: 200px;
-	margin: 0;
+  float: left;
+  margin: 10px 20px 10px 0;
+  overflow:hidden;
 }
 
 table em {
-	font-weight: bold;
-	font-style: normal;
+  font-weight: bold;
+  font-style: normal;
 }
 
 table.LC_tableBrowseRes,
 table.LC_tableOfContent {
-        border:none;
-	border-spacing: 1px;
-	padding: 3px;
-	background-color: #FFFFFF;
-	font-size: 90%;
+  border:none;
+  border-spacing: 1px;
+  padding: 3px;
+  background-color: #FFFFFF;
+  font-size: 90%;
 }
 
-table.LC_tableOfContent{
-    border-collapse: collapse;
+table.LC_tableOfContent {
+  border-collapse: collapse;
 }
 
 table.LC_tableBrowseRes a,
 table.LC_tableOfContent a {
-        background-color: transparent;
-	text-decoration: none;
-}
-
-table.LC_tableBrowseRes tr.LC_trOdd,
-table.LC_tableOfContent tr.LC_trOdd{
-	background-color: #EEEEEE;
+  background-color: transparent;
+  text-decoration: none;
 }
 
 table.LC_tableOfContent img {
-	border: none;
-	height: 1.3em;
-	vertical-align: text-bottom;
-	margin-right: 0.3em;
+  border: none;
+  height: 1.3em;
+  vertical-align: text-bottom;
+  margin-right: 0.3em;
 }
 
 a#LC_content_toolbar_firsthomework {
-	background-image:url(/res/adm/pages/open-first-problem.gif);
-}
-
-a#LC_content_toolbar_launchnav {
-	background-image:url(/res/adm/pages/start-navigation.gif);
-}
-
-a#LC_content_toolbar_closenav {
-	background-image:url(/res/adm/pages/close-navigation.gif);
+  background-image:url(/res/adm/pages/open-first-problem.gif);
 }
 
 a#LC_content_toolbar_everything {
-	background-image:url(/res/adm/pages/show-all.gif);
+  background-image:url(/res/adm/pages/show-all.gif);
 }
 
 a#LC_content_toolbar_uncompleted {
-	background-image:url(/res/adm/pages/show-incomplete-problems.gif);
+  background-image:url(/res/adm/pages/show-incomplete-problems.gif);
 }
 
 #LC_content_toolbar_clearbubbles {
-	background-image:url(/res/adm/pages/mark-discussionentries-read.gif);
+  background-image:url(/res/adm/pages/mark-discussionentries-read.gif);
 }
 
 a#LC_content_toolbar_changefolder {
-	background : url(/res/adm/pages/close-all-folders.gif) top center ;
+  background : url(/res/adm/pages/close-all-folders.gif) top center ;
 }
 
 a#LC_content_toolbar_changefolder_toggled {
-	background-image:url(/res/adm/pages/open-all-folders.gif);
+  background-image:url(/res/adm/pages/open-all-folders.gif);
 }
 
 ul#LC_toolbar li a:hover {
-	background-position: bottom center;
+  background-position: bottom center;
 }
 
 ul#LC_toolbar {
-	padding: 0;
-	margin: 2px;
-	list-style:none;
-	position:relative;
-	background-color:white;
+  padding: 0;
+  margin: 2px;
+  list-style:none;
+  position:relative;
+  background-color:white;
 }
 
 ul#LC_toolbar li {
-	border:1px solid white;
-	padding: 0;
-	margin: 0;
-        float: left;
-	display:inline;
-	vertical-align:middle;
-} 
+  border:1px solid white;
+  padding: 0;
+  margin: 0;
+  float: left;
+  display:inline;
+  vertical-align:middle;
+}
 
 
 a.LC_toolbarItem {
-	display:block;
-	padding: 0;
-	margin: 0;
-	height: 32px;
-	width: 32px;
-	color:white;
-	border: none;
-	background-repeat:no-repeat;
-	background-color:transparent;
+  display:block;
+  padding: 0;
+  margin: 0;
+  height: 32px;
+  width: 32px;
+  color:white;
+  border: none;
+  background-repeat:no-repeat;
+  background-color:transparent;
+}
+
+ul.LC_funclist {
+    margin: 0;
+    padding: 0.5em 1em 0.5em 0;
+}
+
+ul.LC_funclist > li:first-child {
+    font-weight:bold; 
+    margin-left:0.8em;
+}
+
+ul.LC_funclist + ul.LC_funclist {
+    /* 
+       left border as a seperator if we have more than
+       one list 
+    */
+    border-left: 1px solid $sidebg;
+    /* 
+       this hides the left border behind the border of the 
+       outer box if element is wrapped to the next 'line' 
+    */
+    margin-left: -1px;
 }
 
 ul.LC_funclist li {
-  float: left;
+  display: inline;
   white-space: nowrap;
-  height: 35px; /* at least as high as heighest list item */
-  margin: 0 15px 15px 10px;
+  margin: 0 0 0 25px;
+  line-height: 150%;
 }
 
+.LC_hidden {
+  display: none;
+}
 
 END
 }
@@ -6422,8 +6605,8 @@ sub headtag {
     if (!$args->{'frameset'}) {
 	$result .= &Apache::lonhtmlcommon::htmlareaheaders();
     }
-    if ($args->{'force_register'}) {
-	$result .= &Apache::lonmenu::registerurl(1);
+    if ($args->{'force_register'} && $env{'request.noversionuri'} !~ m{^/res/adm/pages/}) {
+        $result .= Apache::lonxml::display_title();
     }
     if (!$args->{'no_nav_bar'} 
 	&& !$args->{'only_body'}
@@ -6449,7 +6632,7 @@ ADDMETA
     $result .= '<title> LON-CAPA '.$title.'</title>'
 	.'<link rel="stylesheet" type="text/css" href="'.$url.'" />'
 	.$head_extra;
-    return $result;
+    return $result.'</head>';
 }
 
 =pod
@@ -6484,10 +6667,6 @@ Inputs: none
 sub xml_begin {
     my $output='';
 
-    if ($env{'internal.start_page'}==1) {
-	&Apache::lonhtmlcommon::init_htmlareafields();
-    }
-
     if ($env{'browser.mathml'}) {
 	$output='<?xml version="1.0"?>'
             #.'<?xml-stylesheet type="text/css" href="/adm/MathML/mathml.css"?>'."\n"
@@ -6506,43 +6685,6 @@ sub xml_begin {
 
 =pod
 
-=item * &endheadtag()
-
-Returns a uniform </head> for LON-CAPA web pages.
-
-Inputs: none
-
-=cut
-
-sub endheadtag {
-    return '</head>';
-}
-
-=pod
-
-=item * &head()
-
-Returns a uniform complete <head>..</head> section for LON-CAPA web pages.
-
-Inputs:
-
-=over 4
-
-$title - optional title for the page
-
-$head_extra - optional extra HTML to put inside the <head>
-
-=back
-
-=cut
-
-sub head {
-    my ($title,$head_extra,$args) = @_;
-    return &headtag($title,$head_extra,$args).&endheadtag();
-}
-
-=pod
-
 =item * &start_page()
 
 Returns a complete <html> .. <body> section for LON-CAPA web pages.
@@ -6580,14 +6722,12 @@ $args - additional optional args support
              skip_phases    -> hash ref of 
                                     head -> skip the <html><head> generation
                                     body -> skip all <body> generation
-             no_inline_link -> if true and in remote mode, don't show the 
-                                    'Switch To Inline Menu' link
              no_auto_mt_title -> prevent &mt()ing the title arg
              inherit_jsmath -> when creating popup window in a page,
                                     should it have jsmath forced on by the
                                     current page
              bread_crumbs ->             Array containing breadcrumbs
-             bread_crumbs_components ->  if exists show it as headline else show only the breadcrumbs
+             bread_crumbs_component ->  if exists show it as headline else show only the breadcrumbs
 
 =back
 
@@ -6598,6 +6738,14 @@ $args - additional optional args support
 sub start_page {
     my ($title,$head_extra,$args) = @_;
     #&Apache::lonnet::logthis("start_page ".join(':',caller(0)));
+#SD
+#I don't see why we copy certain elements of %$args to %head_args
+#head args is passed to headtag() and this routine only reads those
+#keys that are needed. There doesn't happen any writes or any processing
+#of other keys.
+#proposal: just pass $args to headtag instead of \%head_args and delete 
+#marked lines
+#<- MARK
     my %head_args;
     foreach my $arg ('redirect','force_register','domain','function',
 		     'bgcolor','frameset','no_nav_bar','only_body',
@@ -6606,13 +6754,16 @@ sub start_page {
 	    $head_args{$arg} = $args->{$arg};
 	}
     }
+#MARK ->
 
     $env{'internal.start_page'}++;
     my $result;
+
     if (! exists($args->{'skip_phases'}{'head'}) ) {
-	$result.=
-	    &xml_begin().
-	    &headtag($title,$head_extra,\%head_args).&endheadtag();
+        $result .= 
+                  &xml_begin() . &headtag($title,$head_extra,\%head_args);
+#replace prev line by
+#                 &xml_begin() . &headtag($title, $head_extra, $args);
     }
     
     if (! exists($args->{'skip_phases'}{'body'}) ) {
@@ -6626,8 +6777,7 @@ sub start_page {
                          $args->{'function'},       $args->{'add_entries'},
                          $args->{'only_body'},      $args->{'domain'},
                          $args->{'force_register'}, $args->{'no_nav_bar'},
-                         $args->{'bgcolor'},        $args->{'no_inline_link'},
-                         $args);
+                         $args->{'bgcolor'},        $args);
         }
     }
 
@@ -6643,8 +6793,9 @@ sub start_page {
     #            $result .= &build_functionlist();
     #}
 
-    # Don't add anything more if only_body wanted
-    return $result if $args->{'only_body'};
+    # Don't add anything more if only_body wanted or in const space
+    return $result if    $args->{'only_body'} 
+                      || $env{'request.state'} eq 'construct';
 
     #Breadcrumbs
     if (exists($args->{'bread_crumbs'}) or exists($args->{'bread_crumbs_component'})) {
@@ -6666,28 +6817,6 @@ sub start_page {
     return $result;
 }
 
-
-=pod
-
-=item * &head()
-
-Returns a complete </body></html> section for LON-CAPA web pages.
-
-Inputs:         $args - additional optional args supported are:
-                 js_ready     -> return a string ready for being used in 
-                                 a javascript writeln
-                 html_encode  -> return a string ready for being used in 
-                                 a html attribute
-                 frameset     -> if true will start with a <frameset>
-                                 rather than <body>
-                 dicsussion   -> if true will get discussion from
-                                  lonxml::xmlend
-                                 (you can pass the target and parser arguments
-                                  through optional 'target' and 'parser' args
-                                  to this routine)
-
-=cut
-
 sub end_page {
     my ($args) = @_;
     $env{'internal.end_page'}++;
@@ -6762,6 +6891,19 @@ sub validate_page {
     }
 }
 
+
+sub start_scrollbox {
+    my ($outerwidth,$width,$height)=@_;
+    unless ($outerwidth) { $outerwidth='520px'; }
+    unless ($width) { $width='500px'; }
+    unless ($height) { $height='200px'; }
+    return "<table style='width: $outerwidth; border: 1px solid black;'><tr><td style='width: $width;' bgcolor='#FFFFFF'><div style='overflow:auto; width:$width; height: $height;'>";
+}
+
+sub end_scrollbox {
+    return '</td></tr></table>';
+}
+
 sub simple_error_page {
     my ($r,$title,$msg) = @_;
     my $page =
@@ -6777,31 +6919,44 @@ sub simple_error_page {
 
 {
     my @row_count;
+
+    sub start_data_table_count {
+        unshift(@row_count, 0);
+        return;
+    }
+
+    sub end_data_table_count {
+        shift(@row_count);
+        return;
+    }
+
     sub start_data_table {
 	my ($add_class) = @_;
 	my $css_class = (join(' ','LC_data_table',$add_class));
-	unshift(@row_count,0);
+	&start_data_table_count();
 	return '<table class="'.$css_class.'">'."\n";
     }
 
     sub end_data_table {
-	shift(@row_count);
+	&end_data_table_count();
 	return '</table>'."\n";;
     }
 
     sub start_data_table_row {
-	my ($add_class) = @_;
+	my ($add_class, $id) = @_;
 	$row_count[0]++;
 	my $css_class = ($row_count[0] % 2)?'LC_odd_row':'LC_even_row';
 	$css_class = (join(' ',$css_class,$add_class)) unless ($add_class eq '');
-	return  '<tr class="'.$css_class.'">'."\n";;
+        $id = (' id="'.$id.'"') unless ($id eq '');
+        return  '<tr class="'.$css_class.'"'.$id.'>'."\n";
     }
     
     sub continue_data_table_row {
-	my ($add_class) = @_;
+	my ($add_class, $id) = @_;
 	my $css_class = ($row_count[0] % 2)?'LC_odd_row':'LC_even_row';
-	$css_class = (join(' ',$css_class,$add_class)) unless ($add_class eq '');;
-	return  '<tr class="'.$css_class.'">'."\n";;
+	$css_class = (join(' ',$css_class,$add_class)) unless ($add_class eq '');
+        $id = (' id="'.$id.'"') unless ($id eq '');
+        return  '<tr class="'.$css_class.'"'.$id.'>'."\n";
     }
 
     sub end_data_table_row {
@@ -6899,7 +7054,7 @@ sub get_users_function {
     if ($env{'request.role'}=~/^(st)/) {
         $function='student';
     }
-    if ($env{'request.role'}=~/^(cc|in|ta|ep)/) {
+    if ($env{'request.role'}=~/^(cc|co|in|ta|ep)/) {
         $function='coordinator';
     }
     if ($env{'request.role'}=~/^(su|dc|ad|li)/) {
@@ -6964,13 +7119,14 @@ role status: active, previous or future.
 
 sub check_user_status {
     my ($udom,$uname,$cdom,$crs,$role,$sec) = @_;
-    my %userinfo = &Apache::lonnet::dump('roles',$udom,$uname);
+    my $extra = &Apache::lonnet::freeze_escape({'skipcheck' => 1});
+    my %userinfo = &Apache::lonnet::dump('roles',$udom,$uname,'.',undef,$extra);
     my @uroles = keys %userinfo;
     my $srchstr;
     my $active_chk = 'none';
     my $now = time;
     if (@uroles > 0) {
-        if (($role eq 'cc') || ($sec eq '') || (!defined($sec))) {
+        if (($role eq 'cc') || ($role eq 'co') || ($sec eq '') || (!defined($sec))) {
             $srchstr = '/'.$cdom.'/'.$crs.'_'.$role;
         } else {
             $srchstr = '/'.$cdom.'/'.$crs.'/'.$sec.'_'.$role;
@@ -7547,7 +7703,7 @@ sub get_secgrprole_info {
 }
 
 sub user_picker {
-    my ($dom,$srch,$forcenewuser,$caller,$cancreate,$usertype) = @_;
+    my ($dom,$srch,$forcenewuser,$caller,$cancreate,$usertype,$context) = @_;
     my $currdom = $dom;
     my %curr_selected = (
                         srchin => 'dom',
@@ -7638,10 +7794,15 @@ sub user_picker {
     $srchtypesel .= "\n  </select>\n";
 
     my ($newuserscript,$new_user_create);
-
+    my $context_dom = $env{'request.role.domain'};
+    if ($context eq 'requestcrs') {
+        if ($env{'form.coursedom'} ne '') { 
+            $context_dom = $env{'form.coursedom'};
+        }
+    }
     if ($forcenewuser) {
         if (ref($srch) eq 'HASH') {
-            if ($srch->{'srchby'} eq 'uname' && $srch->{'srchtype'} eq 'exact' && $srch->{'srchin'} eq 'dom' && $srch->{'srchdomain'} eq $env{'request.role.domain'}) {
+            if ($srch->{'srchby'} eq 'uname' && $srch->{'srchtype'} eq 'exact' && $srch->{'srchin'} eq 'dom' && $srch->{'srchdomain'} eq $context_dom) {
                 if ($cancreate) {
                     $new_user_create = '<p> <input type="submit" name="forcenew" value="'.&HTML::Entities::encode(&mt('Make new user "[_1]"',$srchterm),'<>&"').'" onclick="javascript:setSearch(\'1\','.$caller.');" /> </p>';
                 } else {
@@ -7680,7 +7841,7 @@ function setSearch(createnew,callingForm
             }
         }
         for (var i=0; i<callingForm.srchdomain.length; i++) {
-            if (callingForm.srchdomain.options[i].value == '$env{'request.role.domain'}') {
+            if (callingForm.srchdomain.options[i].value == '$context_dom') {
                 callingForm.srchdomain.selectedIndex = i;
             }
         }
@@ -8003,6 +8164,10 @@ sub get_institutional_codes {
     return;
 }
 
+sub get_standard_codeitems {
+    return ('Year','Semester','Department','Number','Section');
+}
+
 =pod
 
 =head1 Slot Helpers
@@ -8194,68 +8359,307 @@ sub get_env_multiple {
 
 sub ask_for_embedded_content {
     my ($actionurl,$state,$allfiles,$codebase,$args)=@_;
-    my $upload_output = '
-   <form name="upload_embedded" action="'.$actionurl.'"
-                  method="post" enctype="multipart/form-data">';
-    $upload_output .= $state;
-    $upload_output .= '<b>Upload embedded files</b>:<br />'.&start_data_table();
-
+    my (%subdependencies,%dependencies,%mapping,%existing,%newfiles,%pathchanges);
     my $num = 0;
-    foreach my $embed_file (sort {lc($a) cmp lc($b)} keys(%{$allfiles})) {
+    my $numremref = 0;
+    my $numinvalid = 0;
+    my $numpathchg = 0;
+    my $numexisting = 0;
+    my ($output,$upload_output,$toplevel,$url,$udom,$uname,$getpropath);
+    if (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) {
+        my $current_path='/';
+        if ($env{'form.currentpath'}) {
+            $current_path = $env{'form.currentpath'};
+        }
+        if ($actionurl eq '/adm/coursegrp_portfolio') {
+            $udom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+            $uname = $env{'course.'.$env{'request.course.id'}.'.num'};
+            $url = '/userfiles/groups/'.$env{'form.group'}.'/portfolio';
+        } else {
+            $udom = $env{'user.domain'};
+            $uname = $env{'user.name'};
+            $url = '/userfiles/portfolio';
+        }
+        $toplevel = $url.'/';
+        $url .= $current_path;
+        $getpropath = 1;
+    } elsif (($actionurl eq '/adm/upload') || ($actionurl eq '/adm/testbank') ||
+             ($actionurl eq '/adm/imsimport')) { 
+        ($uname,my $rest) = ($args->{'current_path'} =~ m{/priv/($match_username)/?(.*)$});
+        $url = '/home/'.$uname.'/public_html/';
+        $toplevel = $url;
+        if ($rest ne '') {
+            $url .= $rest;
+        }
+    } elsif ($actionurl eq '/adm/coursedocs') {
+        if (ref($args) eq 'HASH') {
+           $url = $args->{'docs_url'};
+           $toplevel = $url;
+        }
+    }
+    my $now = time();
+    foreach my $embed_file (keys(%{$allfiles})) {
+        my $absolutepath;
+        if ($embed_file =~ m{^\w+://}) {
+            $newfiles{$embed_file} = 1;
+            $mapping{$embed_file} = $embed_file;
+        } else {
+            if ($embed_file =~ m{^/}) {
+                $absolutepath = $embed_file;
+                $embed_file =~ s{^(/+)}{};
+            }
+            if ($embed_file =~ m{/}) {
+                my ($path,$fname) = ($embed_file =~ m{^(.+)/([^/]*)$});
+                $path = &check_for_traversal($path,$url,$toplevel);
+                my $item = $fname;
+                if ($path ne '') {
+                    $item = $path.'/'.$fname;
+                    $subdependencies{$path}{$fname} = 1;
+                } else {
+                    $dependencies{$item} = 1;
+                }
+                if ($absolutepath) {
+                    $mapping{$item} = $absolutepath;
+                } else {
+                    $mapping{$item} = $embed_file;
+                }
+            } else {
+                $dependencies{$embed_file} = 1;
+                if ($absolutepath) {
+                    $mapping{$embed_file} = $absolutepath;
+                } else {
+                    $mapping{$embed_file} = $embed_file;
+                }
+            }
+        }
+    }
+    foreach my $path (keys(%subdependencies)) {
+        my %currsubfile;
+        if (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) { 
+            my @subdir_list = &Apache::lonnet::dirlist($url.$path,$udom,$uname,$getpropath);
+            foreach my $line (@subdir_list) {
+                my ($file_name,$rest) = split(/\&/,$line,2);
+                $currsubfile{$file_name} = 1;
+            }
+        } elsif (($actionurl eq '/adm/upload') || ($actionurl eq '/adm/testbank')) {
+            if (opendir(my $dir,$url.'/'.$path)) {
+                my @subdir_list = grep(!/^\./,readdir($dir));
+                map {$currsubfile{$_} = 1;} @subdir_list;
+            }
+        }
+        foreach my $file (keys(%{$subdependencies{$path}})) {
+            if ($currsubfile{$file}) {
+                my $item = $path.'/'.$file;
+                unless ($mapping{$item} eq $item) {
+                    $pathchanges{$item} = 1;
+                }
+                $existing{$item} = 1;
+                $numexisting ++;
+            } else {
+                $newfiles{$path.'/'.$file} = 1;
+            }
+        }
+    }
+    my %currfile;
+    if (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) {
+        my @dir_list = &Apache::lonnet::dirlist($url,$udom,$uname,$getpropath);
+        foreach my $line (@dir_list) {
+            my ($file_name,$rest) = split(/\&/,$line,2);
+            $currfile{$file_name} = 1;
+        }
+    } elsif (($actionurl eq '/adm/upload') || ($actionurl eq '/adm/testbank')) {
+        if (opendir(my $dir,$url)) {
+            my @dir_list = grep(!/^\./,readdir($dir));
+            map {$currfile{$_} = 1;} @dir_list;
+        }
+    }
+    foreach my $file (keys(%dependencies)) {
+        if ($currfile{$file}) {
+            unless ($mapping{$file} eq $file) {
+                $pathchanges{$file} = 1;
+            }
+            $existing{$file} = 1;
+            $numexisting ++;
+        } else {
+            $newfiles{$file} = 1;
+        }
+    }
+    foreach my $embed_file (sort {lc($a) cmp lc($b)} keys(%newfiles)) {
         $upload_output .= &start_data_table_row().
-            '<td>'.$embed_file.'</td><td>';
+                          '<td><span class="LC_filename">'.$embed_file.'</span>';
+        unless ($mapping{$embed_file} eq $embed_file) {
+            $upload_output .= '<br /><span class="LC_info" style="font-size:smaller;">'.&mt('changed from: [_1]',$mapping{$embed_file}).'</span>';
+        }
+        $upload_output .= '</td><td>';
         if ($args->{'ignore_remote_references'}
             && $embed_file =~ m{^\w+://}) {
             $upload_output.='<span class="LC_warning">'.&mt("URL points to other server.").'</span>';
+            $numremref++;
         } elsif ($args->{'error_on_invalid_names'}
             && $embed_file ne &Apache::lonnet::clean_filename($embed_file,{'keep_path' => 1,})) {
 
-            $upload_output.='<span class="LC_warning">'.&mt("Invalid characters").'</span>';
-
+            $upload_output.='<span class="LC_warning">'.&mt('Invalid characters').'</span>';
+            $numinvalid++;
         } else {
-            $upload_output .='
-           <input name="embedded_item_'.$num.'" type="file" value="" />
-           <input name="embedded_orig_'.$num.'" type="hidden" value="'.&escape($embed_file).'" />';
-            my $attrib = join(':',@{$$allfiles{$embed_file}});
-            $upload_output .=
-                "\n\t\t".
-                '<input name="embedded_attrib_'.$num.'" type="hidden" value="'.
-                $attrib.'" />';
-            if (exists($$codebase{$embed_file})) {
-                $upload_output .=
-                    "\n\t\t".
-                    '<input name="codebase_'.$num.'" type="hidden" value="'.
-                    &escape($$codebase{$embed_file}).'" />';
-            }
-        }
-        $upload_output .= '</td>'.&Apache::loncommon::end_data_table_row();
-        $num++;
-    }
-    $upload_output .= &Apache::loncommon::end_data_table().'<br />
-   <input type ="hidden" name="number_embedded_items" value="'.$num.'" />
-   <input type ="submit" value="'.&mt('Upload Listed Files').'" />
-   '.&mt('(only files for which a location has been provided will be uploaded)').'
-   </form>';
-    return $upload_output;
+            $upload_output .= &embedded_file_element('upload_embedded',$num,
+                                                     $embed_file,\%mapping,
+                                                     $allfiles,$codebase);
+            $num++;
+        }
+        $upload_output .= '</td>'.&Apache::loncommon::end_data_table_row()."\n";
+    }
+    foreach my $embed_file (sort {lc($a) cmp lc($b)} keys(%existing)) {
+        $upload_output .= &start_data_table_row().
+                          '<td><span class="LC_filename">'.$embed_file.'</span></td>'.
+                          '<td><span class="LC_warning">'.&mt('Already exists').'</span></td>'.
+                          &Apache::loncommon::end_data_table_row()."\n";
+    }
+    if ($upload_output) {
+        $upload_output = &start_data_table().
+                         $upload_output.
+                         &end_data_table()."\n";
+    }
+    my $applies = 0;
+    if ($numremref) {
+        $applies ++;
+    }
+    if ($numinvalid) {
+        $applies ++;
+    }
+    if ($numexisting) {
+        $applies ++;
+    }
+    if ($num) {
+        $output = '<form name="upload_embedded" action="'.$actionurl.'"'.
+                  ' method="post" enctype="multipart/form-data">'."\n".
+                  $state.
+                  '<h3>'.&mt('Upload embedded files').
+                  ':</h3>'.$upload_output.'<br />'."\n".
+                  '<input type ="hidden" name="number_embedded_items" value="'.
+                  $num.'" />'."\n";
+        if ($actionurl eq '') {
+            $output .=  '<input type="hidden" name="phase" value="three" />';
+        }
+    } elsif ($applies) {
+        $output = '<b>'.&mt('Referenced files').'</b>:<br />';
+        if ($applies > 1) {
+            $output .=  
+                &mt('No files need to be uploaded, as one of the following applies to each reference:').'<ul>';
+            if ($numremref) {
+                $output .= '<li>'.&mt('reference is to a URL which points to another server').'</li>'."\n";
+            }
+            if ($numinvalid) {
+                $output .= '<li>'.&mt('reference is to file with a name containing invalid characters').'</li>'."\n";
+            }
+            if ($numexisting) {
+                $output .= '<li>'.&mt('reference is to an existing file at the specified location').'</li>'."\n";
+            }
+            $output .= '</ul><br />';
+        } elsif ($numremref) {
+            $output .= '<p>'.&mt('None to upload, as all references are to URLs pointing to another server.').'</p>';
+        } elsif ($numinvalid) {
+            $output .= '<p>'.&mt('None to upload, as all references are to files with names containing invalid characters.').'</p>';
+        } elsif ($numexisting) {
+            $output .= '<p>'.&mt('None to upload, as all references are to existing files.').'</p>';
+        }
+        $output .= $upload_output.'<br />';
+    }
+    my ($pathchange_output,$chgcount);
+    $chgcount = $num;
+    if (keys(%pathchanges) > 0) {
+        foreach my $embed_file (sort {lc($a) cmp lc($b)} keys(%pathchanges)) {
+            if ($num) {
+                $output .= &embedded_file_element('pathchange',$chgcount,
+                                                  $embed_file,\%mapping,
+                                                  $allfiles,$codebase);
+            } else {
+                $pathchange_output .= 
+                    &start_data_table_row().
+                    '<td><input type ="checkbox" name="namechange" value="'.
+                    $chgcount.'" checked="checked" /></td>'.
+                    '<td>'.$mapping{$embed_file}.'</td>'.
+                    '<td>'.$embed_file.
+                    &embedded_file_element('pathchange',$numpathchg,$embed_file,
+                                           \%mapping,$allfiles,$codebase).
+                    '</td>'.&end_data_table_row();
+            }
+            $numpathchg ++;
+            $chgcount ++;
+        }
+    }
+    if ($num) {
+        if ($numpathchg) {
+            $output .= '<input type ="hidden" name="number_pathchange_items" value="'.
+                       $numpathchg.'" />'."\n";
+        }
+        if (($actionurl eq '/adm/upload') || ($actionurl eq '/adm/testbank') || 
+            ($actionurl eq '/adm/imsimport')) {
+            $output .= '<input type="hidden" name="phase" value="three" />'."\n";
+        } elsif ($actionurl eq '/adm/portfolio' || $actionurl eq '/adm/coursegrp_portfolio') {
+            $output .= '<input type="hidden" name="action" value="upload_embedded" />';
+        }
+        $output .=  '<input type ="submit" value="'.&mt('Upload Listed Files').'" />'."\n".
+                    &mt('(only files for which a location has been provided will be uploaded)').'</form>'."\n";
+    } elsif ($numpathchg) {
+        my %pathchange = ();
+        $output .= &modify_html_form('pathchange',$actionurl,$state,\%pathchange,$pathchange_output);
+        if (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) {
+            $output .= '<p>'.&mt('or').'</p>'; 
+        } 
+    }
+    return ($output,$num,$numpathchg);
+}
+
+sub embedded_file_element {
+    my ($context,$num,$embed_file,$mapping,$allfiles,$codebase) = @_;
+    return unless ((ref($mapping) eq 'HASH') && (ref($allfiles) eq 'HASH') &&
+                   (ref($codebase) eq 'HASH'));
+    my $output;
+    if ($context eq 'upload_embedded') {
+       $output = '<input name="embedded_item_'.$num.'" type="file" value="" />'."\n";
+    }
+    $output .= '<input name="embedded_orig_'.$num.'" type="hidden" value="'.
+               &escape($embed_file).'" />';
+    unless (($context eq 'upload_embedded') && 
+            ($mapping->{$embed_file} eq $embed_file)) {
+        $output .='
+        <input name="embedded_ref_'.$num.'" type="hidden" value="'.&escape($mapping->{$embed_file}).'" />';
+    }
+    my $attrib;
+    if (ref($allfiles->{$mapping->{$embed_file}}) eq 'ARRAY') {
+        $attrib = &escape(join(':',@{$allfiles->{$mapping->{$embed_file}}}));
+    }
+    $output .=
+        "\n\t\t".
+        '<input name="embedded_attrib_'.$num.'" type="hidden" value="'.
+        $attrib.'" />';
+    if (exists($codebase->{$mapping->{$embed_file}})) {
+        $output .=
+            "\n\t\t".
+            '<input name="codebase_'.$num.'" type="hidden" value="'.
+            &escape($codebase->{$mapping->{$embed_file}}).'" />';
+    }
+    return $output;
 }
 
 sub upload_embedded {
     my ($context,$dirpath,$uname,$udom,$dir_root,$url_root,$group,$disk_quota,
-        $current_disk_usage) = @_;
-    my $output;
+        $current_disk_usage,$hiddenstate,$actionurl) = @_;
+    my (%pathchange,$output,$modifyform,$footer,$returnflag);
     for (my $i=0; $i<$env{'form.number_embedded_items'}; $i++) {
         next if (!exists($env{'form.embedded_item_'.$i.'.filename'}));
         my $orig_uploaded_filename =
             $env{'form.embedded_item_'.$i.'.filename'};
-
-        $env{'form.embedded_orig_'.$i} =
-            &unescape($env{'form.embedded_orig_'.$i});
+        foreach my $type ('orig','ref','attrib','codebase') {
+            if ($env{'form.embedded_'.$type.'_'.$i} ne '') {
+                $env{'form.embedded_'.$type.'_'.$i} =
+                    &unescape($env{'form.embedded_'.$type.'_'.$i});
+            }
+        }
         my ($path,$fname) =
             ($env{'form.embedded_orig_'.$i} =~ m{(.*/)([^/]*)});
         # no path, whole string is fname
         if (!$fname) { $fname = $env{'form.embedded_orig_'.$i} };
-
-        $path = $env{'form.currentpath'}.$path;
         $fname = &Apache::lonnet::clean_filename($fname);
         # See if there is anything left
         next if ($fname eq '');
@@ -8267,12 +8671,12 @@ sub upload_embedded {
             if ($group ne '') {
                 $port_path = "groups/$group/$port_path";
             }
-            ($state,$msg) = &check_for_upload($path,$fname,$group,'embedded_item_'.$i,
+            ($state,$msg) = &check_for_upload($env{'form.currentpath'}.$path,
+                                              $fname,$group,'embedded_item_'.$i,
                                               $dir_root,$port_path,$disk_quota,
                                               $current_disk_usage,$uname,$udom);
             if ($state eq 'will_exceed_quota'
-                || $state eq 'file_locked'
-                || $state eq 'file_exists' ) {
+                || $state eq 'file_locked') {
                 $output .= $msg;
                 next;
             }
@@ -8286,31 +8690,53 @@ sub upload_embedded {
         # Check if extension is valid
         if (($fname =~ /\.(\w+)$/) &&
             (&Apache::loncommon::fileembstyle($1) eq 'hdn')) {
-            $output .= &mt('Invalid file extension ([_1]) - reserved for LONCAPA use - rename the file with a different extension and re-upload. ',$1);
+            $output .= &mt('Invalid file extension ([_1]) - reserved for LONCAPA use - rename the file with a different extension and re-upload. ',$1).'<br />';
             next;
         } elsif (($fname =~ /\.(\w+)$/) &&
                  (!defined(&Apache::loncommon::fileembstyle($1)))) {
-            $output .= &mt('Unrecognized file extension ([_1]) - rename the file with a proper extension and re-upload.',$1);
+            $output .= &mt('Unrecognized file extension ([_1]) - rename the file with a proper extension and re-upload.',$1).'<br />';
             next;
         } elsif ($fname=~/\.(\d+)\.(\w+)$/) {
-            $output .= &mt('File name not allowed - rename the file to remove the number immediately before the file extension([_1]) and re-upload.',$2);
+            $output .= &mt('File name not allowed - rename the file to remove the number immediately before the file extension([_1]) and re-upload.',$2).'<br />';
             next;
         }
 
         $env{'form.embedded_item_'.$i.'.filename'}=$fname;
         if ($context eq 'portfolio') {
-            my $result=
-                &Apache::lonnet::userfileupload('embedded_item_'.$i,'',
-                                                $dirpath.$path);
+            my $result;
+            if ($state eq 'existingfile') {
+                $result=
+                    &Apache::lonnet::userfileupload('embedded_item_'.$i,'existingfile',
+                                                    $dirpath.$env{'form.currentpath'}.$path);
+            } else {
+                $result=
+                    &Apache::lonnet::userfileupload('embedded_item_'.$i,'',
+                                                    $dirpath.
+                                                    $env{'form.currentpath'}.$path);
+                if ($result !~ m|^/uploaded/|) {
+                    $output .= '<span class="LC_error">'
+                               .&mt('An error occurred ([_1]) while trying to upload [_2] for embedded element [_3].'
+                               ,$result,$orig_uploaded_filename,$env{'form.embedded_orig_'.$i})
+                               .'</span><br />';
+                    next;
+                } else {
+                    $output .= &mt('Uploaded [_1]','<span class="LC_filename">'.
+                               $path.$fname.'</span>').'<br />';     
+                }
+            }
+        } elsif ($context eq 'coursedoc') {
+            my $result =
+                &Apache::lonnet::userfileupload('embedded_item_'.$i,'coursedoc',
+                                                $dirpath.'/'.$path);
             if ($result !~ m|^/uploaded/|) {
                 $output .= '<span class="LC_error">'
-                      .&mt('An error occurred ([_1]) while trying to upload [_2] for embedded element [_3].'
+                           .&mt('An error occurred ([_1]) while trying to upload [_2] for embedded element [_3].'
                            ,$result,$orig_uploaded_filename,$env{'form.embedded_orig_'.$i})
-                      .'</span><br />';
-                next;
+                           .'</span><br />';
+                    next;
             } else {
-                $output .= '<p>'.&mt('Uploaded [_1]','<span class="LC_filename">'.
-                           $path.$fname.'</span>').'</p>';     
+                $output .= &mt('Uploaded [_1]','<span class="LC_filename">'.
+                           $path.$fname.'</span>').'<br />';
             }
         } else {
 # Save the file
@@ -8340,19 +8766,190 @@ sub upload_embedded {
                               &mt('An error occurred while writing the file [_1] for embedded element [_2].',$orig_uploaded_filename,$env{'form.embedded_orig_'.$i}).
                               '</span><br />';
                 } else {
-                    if ($context eq 'testbank') {
-                        $output .= &mt('Embedded file uploaded successfully:').
-                                   '&nbsp;<a href="'.$url.'">'.
-                                   $orig_uploaded_filename.'</a><br />';
-                    } else {
-                        $output .= '<span class=\"LC_fontsize_large\">'.
-                                   &mt('View embedded file: [_1]','<a href="'.$url.'">'.
-                                   $orig_uploaded_filename.'</a>').'</span><br />';
+                    $output .= &mt('Uploaded [_1]','<span class="LC_filename">'.
+                               $url.'</span>').'<br />';
+                    unless ($context eq 'testbank') {
+                        $footer .= &mt('View embedded file: [_1]',
+                                       '<a href="'.$url.'">'.$fname.'</a>').'<br />';
                     }
                 }
                 close($fh);
             }
         }
+        if ($env{'form.embedded_ref_'.$i}) {
+            $pathchange{$i} = 1;
+        }
+    }
+    if ($output) {
+        $output = '<p>'.$output.'</p>';
+    }
+    $output .= &modify_html_form('upload_embedded',$actionurl,$hiddenstate,\%pathchange);
+    $returnflag = 'ok';
+    if (keys(%pathchange) > 0) {
+        if ($context eq 'portfolio') {
+            $output .= '<p>'.&mt('or').'</p>';
+        } elsif ($context eq 'testbank') {
+            $output .=  '<p>'.&mt('Or [_1]continue[_2] the testbank import without modifying the reference(s).','<a href="javascript:document.testbankForm.submit();">','</a>').'</p>';
+            $returnflag = 'modify_orightml';
+        }
+    }
+    return ($output.$footer,$returnflag);
+}
+
+sub modify_html_form {
+    my ($context,$actionurl,$hiddenstate,$pathchange,$pathchgtable) = @_;
+    my $end = 0;
+    my $modifyform;
+    if ($context eq 'upload_embedded') {
+        return unless (ref($pathchange) eq 'HASH');
+        if ($env{'form.number_embedded_items'}) {
+            $end += $env{'form.number_embedded_items'};
+        }
+        if ($env{'form.number_pathchange_items'}) {
+            $end += $env{'form.number_pathchange_items'};
+        }
+        if ($end) {
+            for (my $i=0; $i<$end; $i++) {
+                if ($i < $env{'form.number_embedded_items'}) {
+                    next unless($pathchange->{$i});
+                }
+                $modifyform .=
+                    &start_data_table_row().
+                    '<td><input type ="checkbox" name="namechange" value="'.$i.'" '.
+                    'checked="checked" /></td>'.
+                    '<td>'.$env{'form.embedded_ref_'.$i}.
+                    '<input type="hidden" name="embedded_ref_'.$i.'" value="'.
+                    &escape($env{'form.embedded_ref_'.$i}).'" />'.
+                    '<input type="hidden" name="embedded_codebase_'.$i.'" value="'.
+                    &escape($env{'form.embedded_codebase_'.$i}).'" />'.
+                    '<input type="hidden" name="embedded_attrib_'.$i.'" value="'.
+                    &escape($env{'form.embedded_attrib_'.$i}).'" /></td>'.
+                    '<td>'.$env{'form.embedded_orig_'.$i}.
+                    '<input type="hidden" name="embedded_orig_'.$i.'" value="'.
+                    &escape($env{'form.embedded_orig_'.$i}).'" /></td>'.
+                    &end_data_table_row();
+            } 
+        }
+    } else {
+        $modifyform = $pathchgtable;
+        if (($actionurl eq '/adm/upload') || ($actionurl eq '/adm/testbank')) {
+            $hiddenstate .= '<input type="hidden" name="phase" value="four" />';
+        } elsif (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) {
+            $hiddenstate .= '<input type="hidden" name="action" value="modify_orightml" />';
+        }
+    }
+    if ($modifyform) {
+        return '<h3>'.&mt('Changes in content of HTML file required').'</h3>'."\n".
+               '<p>'.&mt('Changes need to be made to the reference(s) used for one or more of the dependencies, if your HTML file is to work correctly:').'<ol>'."\n".
+               '<li>'.&mt('For consistency between the reference(s) and the location of the corresponding stored file within LON-CAPA.').'</li>'."\n".
+               '<li>'.&mt('To change absolute paths to relative paths, or replace directory traversal via "../" within the original reference.').'</li>'."\n".
+               '</ol></p>'."\n".'<p>'.
+               &mt('LON-CAPA can make the required changes to your HTML file.').'</p>'."\n".
+               '<form method="post" name="refchanger" action="'.$actionurl.'">'.
+               &start_data_table()."\n".
+               &start_data_table_header_row().
+               '<th>'.&mt('Change?').'</th>'.
+               '<th>'.&mt('Current reference').'</th>'.
+               '<th>'.&mt('Required reference').'</th>'.
+               &end_data_table_header_row()."\n".
+               $modifyform.
+               &end_data_table().'<br />'."\n".$hiddenstate.
+               '<input type="submit" name="pathchanges" value="'.&mt('Modify HTML file').'" />'.
+               '</form>'."\n";
+    }
+    return;
+}
+
+sub modify_html_refs {
+    my ($context,$dirpath,$uname,$udom,$dir_root) = @_;
+    my $container;
+    if ($context eq 'portfolio') {
+        $container = $env{'form.container'};
+    } elsif ($context eq 'coursedoc') {
+        $container = $env{'form.primaryurl'};
+    } else {
+        $container = $env{'form.filename'};
+        $container =~ s{^/priv/(\Q$uname\E)/(.*)}{/home/$1/public_html/$2};
+    }
+    my (%allfiles,%codebase,$output,$content);
+    my @changes = &get_env_multiple('form.namechange');
+    return unless (@changes > 0);
+    if (($context eq 'portfolio') || ($context eq 'coursedoc')) {
+        return unless ($container =~ m{^/uploaded/\Q$udom\E/\Q$uname\E/});
+        $content = &Apache::lonnet::getfile($container);
+        return if ($content eq '-1');
+    } else {
+        return unless ($container =~ /^\Q$dir_root\E/); 
+        if (open(my $fh,"<$container")) {
+            $content = join('', <$fh>);
+            close($fh);
+        } else {
+            return;
+        }
+    }
+    my ($count,$codebasecount) = (0,0);
+    my $mm = new File::MMagic;
+    my $mime_type = $mm->checktype_contents($content);
+    if ($mime_type eq 'text/html') {
+        my $parse_result = 
+            &Apache::lonnet::extract_embedded_items($container,\%allfiles,
+                                                    \%codebase,\$content);
+        if ($parse_result eq 'ok') {
+            foreach my $i (@changes) {
+                my $orig = &unescape($env{'form.embedded_orig_'.$i});
+                my $ref = &unescape($env{'form.embedded_ref_'.$i});
+                if ($allfiles{$ref}) {
+                    my $newname =  $orig;
+                    my ($attrib_regexp,$codebase);
+                    $attrib_regexp = &unescape($env{'form.embedded_attrib_'.$i});
+                    if ($attrib_regexp =~ /:/) {
+                        $attrib_regexp =~ s/\:/|/g;
+                    }
+                    if ($content =~ m{($attrib_regexp\s*=\s*['"]?)\Q$ref\E(['"]?)}) {
+                        my $numchg = ($content =~ s{($attrib_regexp\s*=\s*['"]?)\Q$ref\E(['"]?)}{$1$newname$2}gi);
+                        $count += $numchg;
+                    }
+                    if ($env{'form.embedded_codebase_'.$i} ne '') {
+                        $codebase = &unescape($env{'form.embedded_codebase_'.$i});
+                        my $numchg = ($content =~ s/(codebase\s*=\s*["']?)\Q$codebase\E(["']?)/$1.$2/i); #' stupid emacs
+                        $codebasecount ++;
+                    }
+                }
+            }
+            if ($count || $codebasecount) {
+                my $saveresult;
+                if ($context eq 'portfolio' || $context eq 'coursedoc') {
+                    my $url = &Apache::lonnet::store_edited_file($container,$content,$udom,$uname,\$saveresult);
+                    if ($url eq $container) {
+                        my ($fname) = ($container =~ m{/([^/]+)$});
+                        $output = '<p>'.&mt('Updated [quant,_1,reference] in [_2].',
+                                            $count,'<span class="LC_filename">'.
+                                            $fname.'</span>').'</p>'; 
+                    } else {
+                         $output = '<p class="LC_error">'.
+                                   &mt('Error: update failed for: [_1].',
+                                   '<span class="LC_filename">'.
+                                   $container.'</span>').'</p>';
+                    }
+                } else {
+                    if (open(my $fh,">$container")) {
+                        print $fh $content;
+                        close($fh);
+                        $output = '<p>'.&mt('Updated [quant,_1,reference] in [_2].',
+                                  $count,'<span class="LC_filename">'.
+                                  $container.'</span>').'</p>';
+                    } else {
+                         $output = '<p class="LC_error">'.
+                                   &mt('Error: could not update [_1].',
+                                   '<span class="LC_filename">'.
+                                   $container.'</span>').'</p>';
+                    }
+                }
+            }
+        } else {
+            &logthis('Failed to parse '.$container.
+                     ' to modify references: '.$parse_result);
+        }
     }
     return $output;
 }
@@ -8376,22 +8973,71 @@ sub check_for_existing {
 sub check_for_upload {
     my ($path,$fname,$group,$element,$portfolio_root,$port_path,
         $disk_quota,$current_disk_usage,$uname,$udom) = @_;
-    my $filesize = (length($env{'form.'.$element})) / 1000; #express in k (1024?)
+    my $filesize = length($env{'form.'.$element});
+    if (!$filesize) {
+        my $msg = '<span class="LC_error">'.
+                  &mt('Unable to upload [_1]. (size = [_2] bytes)', 
+                      '<span class="LC_filename">'.$fname.'</span>',
+                      $filesize).'<br />'.
+                  &mt('Either the file you attempted to upload was empty, or your web browser was unable to read its contents.').'<br />'.
+                  '</span>';
+        return ('zero_bytes',$msg);
+    }
+    $filesize =  $filesize/1000; #express in k (1024?)
     my $getpropath = 1;
     my @dir_list = &Apache::lonnet::dirlist($portfolio_root.$path,$udom,$uname,
                                             $getpropath);
     my $found_file = 0;
     my $locked_file = 0;
+    my @lockers;
+    my $navmap;
+    if ($env{'request.course.id'}) {
+        $navmap = Apache::lonnavmaps::navmap->new();
+    }
     foreach my $line (@dir_list) {
-        my ($file_name)=split(/\&/,$line,2);
+        my ($file_name,$rest)=split(/\&/,$line,2);
         if ($file_name eq $fname){
             $file_name = $path.$file_name;
             if ($group ne '') {
                 $file_name = $group.$file_name;
             }
             $found_file = 1;
-            if (&Apache::lonnet::is_locked($file_name,$udom,$uname) eq 'true') {
-                $locked_file = 1;
+            if (&Apache::lonnet::is_locked($file_name,$udom,$uname,\@lockers) eq 'true') {
+                foreach my $lock (@lockers) {
+                    if (ref($lock) eq 'ARRAY') {
+                        my ($symb,$crsid) = @{$lock};
+                        if ($crsid eq $env{'request.course.id'}) {
+                            if (ref($navmap)) {
+                                my $res = $navmap->getBySymb($symb);
+                                foreach my $part (@{$res->parts()}) { 
+                                    my ($slot_status,$slot_time,$slot_name)=$res->check_for_slot($part);
+                                    unless (($slot_status == $res->RESERVED) ||
+                                            ($slot_status == $res->RESERVED_LOCATION)) {
+                                        $locked_file = 1;
+                                    }
+                                }
+                            } else {
+                                $locked_file = 1;
+                            }
+                        } else {
+                            $locked_file = 1;
+                        }
+                    }
+                }
+            } else {
+                my @info = split(/\&/,$rest);
+                my $currsize = $info[6]/1000;
+                if ($currsize < $filesize) {
+                    my $extra = $filesize - $currsize;
+                    if (($current_disk_usage + $extra) > $disk_quota) {
+                        my $msg = '<span class="LC_error">'.
+                                  &mt('Unable to upload [_1]. (size = [_2] kilobytes). Disk quota will be exceeded if existing (smaller) file with same name (size = [_3] kilobytes) is replaced.',
+                                      '<span class="LC_filename">'.$fname.'</span>',$filesize,$currsize).'</span>'.
+                                  '<br />'.&mt('Disk quota is [_1] kilobytes. Your current disk usage is [_2] kilobytes.',
+                                               $disk_quota,$current_disk_usage);
+                        return ('will_exceed_quota',$msg);
+                    }
+                }
             }
         }
     }
@@ -8409,15 +9055,55 @@ sub check_for_upload {
             return ('file_locked',$msg);
         } else {
             my $msg = '<span class="LC_error">';
-            $msg .= &mt('Unable to upload [_1]. A file by that name was found in [_2].','<span class="LC_filename">'.$fname.'</span>',$port_path.$env{'form.currentpath'});
+            $msg .= &mt(' A file by that name: [_1] was found in [_2].','<span class="LC_filename">'.$fname.'</span>',$port_path.$env{'form.currentpath'});
             $msg .= '</span>';
-            $msg .= '<br />';
-            $msg .= &mt('To upload, rename or delete existing [_1] in [_2].','<span class="LC_filename">'.$fname.'</span>', $port_path.$env{'form.currentpath'});
-            return ('file_exists',$msg);
+            return ('existingfile',$msg);
         }
     }
 }
 
+sub check_for_traversal {
+    my ($path,$url,$toplevel) = @_;
+    my @parts=split(/\//,$path);
+    my $cleanpath;
+    my $fullpath = $url;
+    for (my $i=0;$i<@parts;$i++) {
+        next if ($parts[$i] eq '.');
+        if ($parts[$i] eq '..') {
+            $fullpath =~ s{([^/]+/)$}{};
+        } else {
+            $fullpath .= $parts[$i].'/';
+        }
+    }
+    if ($fullpath =~ /^\Q$url\E(.*)$/) {
+        $cleanpath = $1;
+    } elsif ($fullpath =~ /^\Q$toplevel\E(.*)$/) {
+        my $curr_toprel = $1;
+        my @parts = split(/\//,$curr_toprel);
+        my ($url_toprel) = ($url =~ /^\Q$toplevel\E(.*)$/);
+        my @urlparts = split(/\//,$url_toprel);
+        my $doubledots;
+        my $startdiff = -1;
+        for (my $i=0; $i<@urlparts; $i++) {
+            if ($startdiff == -1) {
+                unless ($urlparts[$i] eq $parts[$i]) {
+                    $startdiff = $i;
+                    $doubledots .= '../';
+                }
+            } else {
+                $doubledots .= '../';
+            }
+        }
+        if ($startdiff > -1) {
+            $cleanpath = $doubledots;
+            for (my $i=$startdiff; $i<@parts; $i++) {
+                $cleanpath .= $parts[$i].'/';
+            }
+        }
+    }
+    $cleanpath =~ s{(/)$}{};
+    return $cleanpath;
+}
 
 =pod
 
@@ -9524,6 +10210,8 @@ sub extract_categories {
                 my $trailstr;
                 if ($name eq 'instcode') {
                     $trailstr = &mt('Official courses (with institutional codes)');
+                } elsif ($name eq 'communities') {
+                    $trailstr = &mt('Communities');
                 } else {
                     $trailstr = $name;
                 }
@@ -9636,12 +10324,14 @@ cathash - reference to hash of categorie
 
 currcat - scalar with an & separated list of categories assigned to a course. 
 
+type    - scalar contains course type (Course or Community).
+
 Returns: $output (markup to be displayed) 
 
 =cut
 
 sub assign_categories_table {
-    my ($cathash,$currcat) = @_;
+    my ($cathash,$currcat,$type) = @_;
     my $output;
     if (ref($cathash) eq 'HASH') {
         my (@cats,@trails,%allitems,%idx,@jsarray,@path,$maxdepth);
@@ -9650,15 +10340,20 @@ sub assign_categories_table {
         if (@cats > 0) {
             my $itemcount = 0;
             if (ref($cats[0]) eq 'ARRAY') {
-                $output = &Apache::loncommon::start_data_table();
                 my @currcategories;
                 if ($currcat ne '') {
                     @currcategories = split('&',$currcat);
                 }
+                my $table;
                 for (my $i=0; $i<@{$cats[0]}; $i++) {
                     my $parent = $cats[0][$i];
-                    my $css_class = $itemcount%2?' class="LC_odd_row"':'';
                     next if ($parent eq 'instcode');
+                    if ($type eq 'Community') {
+                        next unless ($parent eq 'communities');
+                    } else {
+                        next if ($parent eq 'communities');
+                    }
+                    my $css_class = $itemcount%2?' class="LC_odd_row"':'';
                     my $item = &escape($parent).'::0';
                     my $checked = '';
                     if (@currcategories > 0) {
@@ -9666,18 +10361,26 @@ sub assign_categories_table {
                             $checked = ' checked="checked"';
                         }
                     }
-                    $output .= '<tr '.$css_class.'><td><span class="LC_nobreak">'.
-                               '<input type="checkbox" name="usecategory" value="'.
-                               $item.'"'.$checked.' />'.$parent.'</span>'.
-                               '<input type="hidden" name="catname" value="'.$parent.'" /></td>';
+                    my $parent_title = $parent;
+                    if ($parent eq 'communities') {
+                        $parent_title = &mt('Communities');
+                    }
+                    $table .= '<tr '.$css_class.'><td><span class="LC_nobreak">'.
+                              '<input type="checkbox" name="usecategory" value="'.
+                              $item.'"'.$checked.' />'.$parent_title.'</span>'.
+                              '<input type="hidden" name="catname" value="'.$parent.'" /></td>';
                     my $depth = 1;
                     push(@path,$parent);
-                    $output .= &assign_category_rows($itemcount,\@cats,$depth,$parent,\@path,\@currcategories);
+                    $table .= &assign_category_rows($itemcount,\@cats,$depth,$parent,\@path,\@currcategories);
                     pop(@path);
-                    $output .= '</tr><tr><td colspan="'.$maxdepth.'" class="LC_row_separator"></td></tr>';
+                    $table .= '</tr><tr><td colspan="'.$maxdepth.'" class="LC_row_separator"></td></tr>';
                     $itemcount ++;
                 }
-                $output .= &Apache::loncommon::end_data_table();
+                if ($itemcount) {
+                    $output = &Apache::loncommon::start_data_table().
+                              $table.
+                              &Apache::loncommon::end_data_table();
+                }
             }
         }
     }
@@ -9922,11 +10625,24 @@ sub check_clone {
     my $clonehome=&Apache::lonnet::homeserver($clonecrsunum,$clonecrsudom);
     my $clonemsg;
     my $can_clone = 0;
-
+    my $lctype = lc($args->{'crstype'});
+    if ($lctype ne 'community') {
+        $lctype = 'course';
+    }
     if ($clonehome eq 'no_host') {
-        $clonemsg = &mt('No new course created.').$linefeed.&mt('A new course could not be cloned from the specified original - [_1] - because it is a non-existent course.',$args->{'clonecourse'}.':'.$args->{'clonedomain'});     
+        if ($args->{'crstype'} eq 'Community') {
+            $clonemsg = &mt('No new community created.').$linefeed.&mt('A new community could not be cloned from the specified original - [_1] - because it is a non-existent community.',$args->{'clonecourse'}.':'.$args->{'clonedomain'});
+        } else {
+            $clonemsg = &mt('No new course created.').$linefeed.&mt('A new course could not be cloned from the specified original - [_1] - because it is a non-existent course.',$args->{'clonecourse'}.':'.$args->{'clonedomain'});
+        }     
     } else {
 	my %clonedesc = &Apache::lonnet::coursedescription($cloneid,{'one_time' => 1});
+        if ($args->{'crstype'} eq 'Community') {
+            if ($clonedesc{'type'} ne 'Community') {
+                 $clonemsg = &mt('No new community created.').$linefeed.&mt('A new community could not be cloned from the specified original - [_1] - because it is a course not a community.',$args->{'clonecourse'}.':'.$args->{'clonedomain'});
+                return ($can_clone, $clonemsg, $cloneid, $clonehome);
+            }
+        }
 	if (($env{'request.role.domain'} eq $args->{'clonedomain'}) && 
             (&Apache::lonnet::allowed('ccc',$env{'request.role.domain'}))) {
 	    $can_clone = 1;
@@ -9939,15 +10655,25 @@ sub check_clone {
             } elsif (grep(/^\*\:\Q$args->{'ccdomain'}\E$/,@cloners)) {
                 $can_clone = 1;
             } else {
+                my $ccrole = 'cc';
+                if ($args->{'crstype'} eq 'Community') {
+                    $ccrole = 'co';
+                }
 	        my %roleshash =
 		    &Apache::lonnet::get_my_roles($args->{'ccuname'},
 					 $args->{'ccdomain'},
-                                         'userroles',['active'],['cc'],
+                                         'userroles',['active'],[$ccrole],
 					 [$args->{'clonedomain'}]);
-	        if (($roleshash{$args->{'clonecourse'}.':'.$args->{'clonedomain'}.':cc'}) || (grep(/^\Q$args->{'ccuname'}\E:\Q$args->{'ccdomain'}\E$/,@cloners))) {
-		    $can_clone = 1;
-	        } else {
-                    $clonemsg = &mt('No new course created.').$linefeed.&mt('The new course could not be cloned from the existing course because the new course owner ([_1]) does not have cloning rights in the existing course ([_2]).',$args->{'ccuname'}.':'.$args->{'ccdomain'},$clonedesc{'description'});
+	        if (($roleshash{$args->{'clonecourse'}.':'.$args->{'clonedomain'}.':'.$ccrole}) || (grep(/^\Q$args->{'ccuname'}\E:\Q$args->{'ccdomain'}\E$/,@cloners))) {
+                    $can_clone = 1;
+                } elsif (&Apache::lonnet::is_course_owner($args->{'clonedomain'},$args->{'clonecourse'},$args->{'ccuname'},$args->{'ccdomain'})) {
+                    $can_clone = 1;
+                } else {
+                    if ($args->{'crstype'} eq 'Community') {
+                        $clonemsg = &mt('No new community created.').$linefeed.&mt('The new community could not be cloned from the existing community because the new community owner ([_1]) does not have cloning rights in the existing community ([_2]).',$args->{'ccuname'}.':'.$args->{'ccdomain'},$clonedesc{'description'});
+                    } else {
+                        $clonemsg = &mt('No new course created.').$linefeed.&mt('The new course could not be cloned from the existing course because the new course owner ([_1]) does not have cloning rights in the existing course ([_2]).',$args->{'ccuname'}.':'.$args->{'ccdomain'},$clonedesc{'description'});
+                    }
 	        }
 	    }
         }
@@ -10002,11 +10728,19 @@ sub construct_course {
     # if anyone ever decides to not show this, and Utils::Course::new
     # will need to be suitably modified.
     $outcome .= &mt('New LON-CAPA [_1] ID: [_2]',$crstype,$$courseid).$linefeed;
+    if ($$courseid =~ /^error:/) {
+        return (0,$outcome);
+    }
+
 #
 # Check if created correctly
 #
     ($$crsudom,$$crsunum)= &LONCAPA::split_courseid($$courseid);
     my $crsuhome=&Apache::lonnet::homeserver($$crsunum,$$crsudom);
+    if ($crsuhome eq 'no_host') {
+        $outcome .= &mt('Course creation failed, unrecognized course home server.').$linefeed;
+        return (0,$outcome);
+    }
     $outcome .= &mt('Created on').': '.$crsuhome.$linefeed;
 
 #
@@ -10025,6 +10759,10 @@ sub construct_course {
 	$cenv{'url'}=$oldcenv{'url'};
 # Restore title
 	$cenv{'description'}=$oldcenv{'description'};
+# Restore creation date, creator and creation context.
+        $cenv{'internal.created'}=$oldcenv{'internal.created'};
+        $cenv{'internal.creator'}=$oldcenv{'internal.creator'};
+        $cenv{'internal.creationcontext'}=$oldcenv{'internal.creationcontext'};
 # Mark as cloned
 	$cenv{'clonedfrom'}=$cloneid;
 # Need to clone grading mode
@@ -10271,7 +11009,7 @@ sub construct_course {
 	    $title=&mt('Syllabus');
             $url='/public/'.$$crsudom.'/'.$$crsunum.'/syllabus';
         } else {
-            $title=&mt('Navigate Contents');
+            $title=&mt('Table of Contents');
             $url='/adm/navmaps';
         }
 
@@ -10288,6 +11026,8 @@ sub construct_course {
 ############################################################
 ############################################################
 
+#SD
+# only Community and Course, or anything else?
 sub course_type {
     my ($cid) = @_;
     if (!defined($cid)) {
@@ -10453,15 +11193,12 @@ sub init_user_environment {
     my %userenv = &Apache::lonnet::dump('environment',$domain,$username);
     my ($tmp) = keys(%userenv);
     if ($tmp !~ /^(con_lost|error|no_such_host)/i) {
-	# default remote control to off
-	if ($userenv{'remote'} ne 'on') { $userenv{'remote'} = 'off'; }
     } else {
 	undef(%userenv);
     }
     if (($userenv{'interface'}) && (!$form->{'interface'})) {
 	$form->{'interface'}=$userenv{'interface'};
     }
-    $env{'environment.remote'}=$userenv{'remote'};
     if ($userenv{'texengine'} eq 'ttm') { $clientmathml=1; }
 
 # --------------- Do not trust query string to be put directly into environment
@@ -10493,24 +11230,26 @@ sub init_user_environment {
 	    $initial_env{"browser.localres"}   = $form->{'localres'};
         }
 	
-	if ($public) {
-	    $initial_env{"environment.remote"} = "off";
-	}
 	if ($form->{'interface'}) {
 	    $form->{'interface'}=~s/\W//gs;
 	    $initial_env{"browser.interface"} = $form->{'interface'};
 	    $env{'browser.interface'}=$form->{'interface'};
 	}
 
+        my %is_adv = ( is_adv => $env{'user.adv'} );
+        my %domdef = &Apache::lonnet::get_domain_defaults($domain);
+
         foreach my $tool ('aboutme','blog','portfolio') {
             $userenv{'availabletools.'.$tool} = 
-                &Apache::lonnet::usertools_access($username,$domain,$tool,'reload');
+                &Apache::lonnet::usertools_access($username,$domain,$tool,'reload',
+                                                  undef,\%userenv,\%domdef,\%is_adv);
         }
 
         foreach my $crstype ('official','unofficial','community') {
             $userenv{'canrequest.'.$crstype} =
                 &Apache::lonnet::usertools_access($username,$domain,$crstype,
-                                                  'reload','requestcourses');
+                                                  'reload','requestcourses',
+                                                  \%userenv,\%domdef,\%is_adv);
         }
 
 	$env{'user.environment'} = "$lonids/$cookie.id";
@@ -10589,6 +11328,36 @@ sub clean_symb {
     return ($symb,$enc);
 }
 
+sub build_release_hashes {
+    my ($checkparms,$checkresponsetypes,$checkcrstypes,$anonsurvey,$randomizetry) = @_;
+    return unless((ref($checkparms) eq 'HASH') && (ref($checkresponsetypes) eq 'HASH') &&
+                  (ref($checkcrstypes) eq 'HASH') && (ref($anonsurvey) eq 'HASH') &&
+                  (ref($randomizetry) eq 'HASH'));
+    foreach my $key (keys(%Apache::lonnet::needsrelease)) {
+        my ($item,$name,$value) = split(/:/,$key);
+        if ($item eq 'parameter') {
+            if (ref($checkparms->{$name}) eq 'ARRAY') {
+                unless(grep(/^\Q$name\E$/,@{$checkparms->{$name}})) {
+                    push(@{$checkparms->{$name}},$value);
+                }
+            } else {
+                push(@{$checkparms->{$name}},$value);
+            }
+        } elsif ($item eq 'resourcetag') {
+            if ($name eq 'responsetype') {
+                $checkresponsetypes->{$value} = $Apache::lonnet::needsrelease{$key}
+            }
+        } elsif ($item eq 'course') {
+            if ($name eq 'crstype') {
+                $checkcrstypes->{$value} = $Apache::lonnet::needsrelease{$key};
+            }
+        }
+    }
+    ($anonsurvey->{major},$anonsurvey->{minor}) = split(/\./,$Apache::lonnet::needsrelease{'parameter:type:anonsurvey'});
+    ($randomizetry->{major},$randomizetry->{minor}) = split(/\./,$Apache::lonnet::needsrelease{'parameter:type:randomizetry'});
+    return;
+}
+
 =pod
 
 =back