--- loncom/interface/lonmenu.pm	2023/07/06 16:55:43	1.533
+++ loncom/interface/lonmenu.pm	2024/05/14 15:53:17	1.553
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Routines to control the menu
 #
-# $Id: lonmenu.pm,v 1.533 2023/07/06 16:55:43 raeburn Exp $
+# $Id: lonmenu.pm,v 1.553 2024/05/14 15:53:17 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -245,7 +245,7 @@ sub prep_menuitem {
 # @primary_menu is filled within the BEGIN block of this module with 
 # entries from mydesk.tab
 sub primary_menu {
-    my ($crstype,$ltimenu,$menucoll,$menuref,$links_disabled,$links_target) = @_;
+    my ($crstype,$ltimenu,$menucoll,$menuref,$links_disabled,$links_target,$collapsible) = @_;
     my (%menu,%ltiexc,%menuopts);
     # each element of @primary contains following array:
     # (link url, icon path, alt text, link text, condition, position)
@@ -366,6 +366,19 @@ sub primary_menu {
                              ($item->[2] eq 'blog')) &&
                              (!&Apache::lonnet::usertools_access('','',$item->[2],
                                                            undef,'tools')));
+                    if (($item->[2] eq 'browsepub') && ($item->[0] eq '/res/')) {
+                        if ($env{'request.role'} =~ /^au\./) {
+                            $item->[0] .= $env{'request.role.domain'}.'/?launch=1';
+                        } elsif ($env{'request.role'} =~ m{^ca\./($match_domain)/($match_username)$}) {
+                            $item->[0] .= $1.'/'.$2.'/?launch=1';
+                        } elsif (&Apache::lonnet::allowed('bre',$env{'user.domain'})) {
+                            $item->[0] .= $env{'user.domain'}.'/?launch=1';
+                        } elsif (&Apache::lonnet::allowed('bro','/res/')) {
+                            $item->[0] .= '?launch=1';
+                        } else {
+                            next;
+                        }
+                    }
                     if ($env{'request.course.id'} && $menucoll) {
                         next if ($item->[3]) && (!$menuopts{$item->[3]});
                     }
@@ -421,6 +434,10 @@ sub primary_menu {
     }
     my @output = ('','');
     if ($menu{'left'} ne '') {
+        if ($collapsible) {
+            $menu{'left'} = ($listclass?'<li class="'.$listclass.'">':'<li>').
+                            '&nbsp;</li>'.$menu{'left'};
+        }
         $output[0] = "<ol class=\"LC_primary_menu LC_floatleft\">$menu{'left'}</ol>";
     }
     if ($menu{'right'} ne '') {
@@ -436,10 +453,10 @@ sub primary_menu {
 #
 #TODO this should probably be moved somewhere more central
 #since it can be used by different parts of the system
-sub getauthor{
+sub getauthor {
     return unless $env{'request.role'}=~/^(ca|aa|au)/; #nothing to do if user isn't some kind of author
 
-                        #co- or assistent author?
+                        #co- or assistant author?
     my ($dom, $user) = ($env{'request.role'} =~ /^(?:ca|aa)\.\/($match_domain)\/($match_username)$/)
                        ? ($1, $2) #domain, username of the parent author
                        : @env{ ('request.role.domain', 'user.name') }; #own domain, username
@@ -480,6 +497,15 @@ sub secondary_menu {
     my $canplc        = &Apache::lonnet::allowed('plc', $crs_sec);
     my $author        = &getauthor();
 
+    my ($is_author,$is_coauthor);
+    if ($author) {
+        if ($env{'request.role'} =~ /^au\./) {
+            $is_author = 1;
+        } elsif ($env{'request.role'} =~ /^ca\./) {
+            $is_coauthor = 1;
+        }
+    }
+
     my ($cdom,$cnum,$showsyllabus,$showfeeds,$showresv,$grouptools,
         $lti,$ltimapres,%ltiexc,%menuopts);
     $grouptools = 0;
@@ -539,15 +565,25 @@ sub secondary_menu {
         $linkattr = 'aria-disabled="true"';
     }
 
-    my ($canmodifycoauthor); 
+    my ($canlistcoauthors,$canmodifycoauthor);
     if ($env{'request.role'} eq "au./$env{'user.domain'}/") {
         my $extent = "$env{'user.domain'}/$env{'user.name'}";
         if ((&Apache::lonnet::allowed('cca',$extent)) ||
             (&Apache::lonnet::allowed('caa',$extent))) {
             $canmodifycoauthor = 1;
         }
+    } elsif ($env{'request.role'} =~ m{^(aa|ca)\./($match_domain/$match_username)$}) {
+        my ($role,$extent) = ($1,$2);
+        if (&Apache::lonnet::allowed('vca',$extent)) {
+            if ($env{"environment.internal.manager./$extent"}) {
+                $canmodifycoauthor = 1;
+            } else {
+                $canlistcoauthors = 1;
+            }
+        } elsif (&Apache::lonnet::allowed('vaa',$extent)) {
+            $canlistcoauthors = 1;
+        }
     }
-
     my ($roleswitcher_js,$roleswitcher_form);
     if ($links_target ne '') {
         $target = $links_target;
@@ -570,8 +606,12 @@ sub secondary_menu {
         # evaluate conditions 
         next if    ref($menuitem)  ne 'ARRAY';
         next if (($crstype eq 'Placement') && ($$menuitem[3] ne 'Roles') && (!$env{'request.role.adv'}));
-        next if    $$menuitem[4]   ne 'always'
-                && ($$menuitem[4]   ne 'author' && $$menuitem[4] ne 'cca')
+        next if    $$menuitem[4]  ne 'always'
+                && $$menuitem[4]  ne 'coauthor'
+                && $$menuitem[4]  ne 'author'
+                && $$menuitem[4]  ne 'authorspace'
+                && $$menuitem[4]  ne 'vca'
+                && $$menuitem[4]  ne 'mca'
                 && !$env{'request.course.id'};
         next if    $$menuitem[4]   =~ /^crsedit/
                 && (!$canedit && !$canvieweditor);
@@ -599,9 +639,17 @@ sub secondary_menu {
                 && !$showfeeds;
         next if     $$menuitem[4]  eq 'plc'
                 && !$canplc;
-        next if    $$menuitem[4]    eq 'author'
+        next if    $$menuitem[4]   eq 'authorspace'
                 && !$author;
-        next if    $$menuitem[4]    eq 'cca'
+        next if    $$menuitem[4]   eq 'author'
+                && !$is_author;
+        next if    $$menuitem[4]   eq 'coauthor'
+                && !$is_coauthor;
+        next if    $$menuitem[4]    eq 'vca'
+                && (!$canlistcoauthors || $canmodifycoauthor);
+        next if    $$menuitem[4]    eq 'vaa'
+                && (!$canlistcoauthors || $canmodifycoauthor);
+        next if    $$menuitem[4]    eq 'mca'
                 && !$canmodifycoauthor;
         next if    $$menuitem[4]    eq 'notltimapres'
                 && $ltimapres;
@@ -637,8 +685,8 @@ sub secondary_menu {
                         next if ($item->[2] eq 'vcg' && !$canviewgrps);
                         next if ($item->[2] eq 'crsedit' && !$canedit && !$canvieweditor);
                         next if ($item->[2] eq 'params' && !$canmodpara && !$canviewpara);
-                        next if ($item->[2] eq 'author' && !$author);
-                        next if ($item->[2] eq 'cca' && !$canmodifycoauthor);
+                        next if ($item->[2] eq 'author' && !$is_author);
+                        next if ($item->[2] eq 'vca' && !$canlistcoauthors);
                         next if ($item->[2] eq 'lti' && !$lti);
                         if ($item->[2] =~ /^lti(portfolio|wishlist|blog)$/) {
                             my $tool = $1;
@@ -724,6 +772,20 @@ sub secondary_menu {
         }
         $menu =~ s/\[url\]/$escurl/g;
         $menu =~ s/\[symb\]/$escsymb/g;
+    } elsif (($menu =~ m{/adm/preferences\?}) && ($menu =~ /\[returnurl\]/)) {
+        my $returnurl = $ENV{'REQUEST_URI'};
+        if ($ENV{'REQUEST_URI'} =~ m{/adm/preferences\?action=authorsettings\&returnurl=([^\&]+)$}) {
+            $returnurl = $1;
+        }
+        if (($returnurl =~ m{^/adm/createuser($|\?action=)}) ||
+            ($returnurl =~ m{^/priv/$match_domain/$match_username}) ||
+            ($returnurl =~ m{^/res(/?$|/$match_domain/$match_username)})) {
+            $returnurl =~ s{\?.*$}{};
+            $returnurl = '&amp;returnurl='.&HTML::Entities::encode($returnurl,'"<>&\'');
+        } else {
+            undef($returnurl);
+        }
+        $menu =~ s/\[returnurl\]/$returnurl/;
     }
     $menu =~ s/\[uname\]/$$author{user}/g;
     $menu =~ s/\[udom\]/$$author{dom}/g;
@@ -848,7 +910,7 @@ sub innerregister {
     my ($forcereg,$bread_crumbs,$group,$pagebuttonshide,$hostname,
         $ltiscope,$ltiuri,$showncrumbsref) = @_;
     my $const_space = ($env{'request.state'} eq 'construct');
-    my $is_const_dir = 0;
+    my $in_daxe = 0;
 
     if ($env{'request.noversionuri'} =~ m{^/res/adm/pages/}) { return ''; }
 
@@ -968,6 +1030,18 @@ sub innerregister {
                     $$showncrumbsref = 1;
                 }
                 return $trail;
+            } elsif (($resurl eq '/public'.$courseurl.'/syllabus') &&
+                     ($env{'form.folderpath'})) {
+                if ($env{'form.title'}) {
+                    $title = $env{'form.title'};
+                } else {
+                    $title = 'Syllabus';
+                }
+                &prepare_functions($resurl,$forcereg,$group,undef,undef,1,$hostname);
+                $title = &HTML::Entities::encode($title,'\'"<>&');
+                my ($trail) =
+                    &Apache::lonhtmlcommon::docs_breadcrumbs(undef,$crstype,undef,$title,1,1);
+                return $trail;
             }
             unless ($env{'request.state'} eq 'construct') {
                 &Apache::lonhtmlcommon::clear_breadcrumbs();
@@ -1069,11 +1143,30 @@ sub innerregister {
         if (($env{'request.symb'} ne '') &&
             ($env{'request.filename'}=~/$LONCAPA::assess_re/) &&
             (($perms{'mgr'}) || ($perms{'vgr'}))) {
-            my ($viewas,$text,$change,$visibility,$vuname,$vudom,$vid,$leftvis,$defdom,$righticon);
+            my ($viewas,$text,$change,$visibility,$vuname,$vudom,$vid,$leftvis,$defdom,
+                $domselector,$righticon);
             my %lt = &Apache::lonlocal::texthash(
                                                  view => 'View',
                                                  upda => 'Update',
             );
+            my $possdomstr = $env{'course.'.$env{'request.course.id'}.'.internal.userdomains'};
+            if ($possdomstr =~ /,/) {
+                my @possdoms = split(/,/,$possdomstr);
+                if ($env{'request.user_in_effect'} =~ /^$match_username:($match_domain)$/) {
+                    $defdom = $1;
+                } elsif (grep(/^\Q$cdom\E$/,@possdoms)) {
+                    $defdom = $cdom;
+                } elsif (&Apache::lonnet::domain($possdoms[0]) ne '') {
+                    $defdom = $possdoms[0];
+                }
+                $domselector = &Apache::loncommon::select_dom_form($defdom,'vudom','','','',\@possdoms);
+            } elsif (($possdomstr ne '') && (&Apache::lonnet::domain($possdomstr) ne '')) {
+                if ($env{'request.user_in_effect'} =~ /^$match_username:($match_domain)$/) {
+                    $defdom = $1;
+                } else {
+                    $defdom = $possdomstr;
+                }
+            }
             if ($env{'request.user_in_effect'} =~ /^($match_username):($match_domain)$/) {
                 ($vuname,$vudom) = ($1,$2);
                 unless (&Apache::lonnet::is_advanced_user($vudom,$vuname)) {
@@ -1091,17 +1184,29 @@ sub innerregister {
                 $change = 'on';
                 $visibility = 'none';
                 $leftvis = 'inline';
-                $defdom = $cdom;
+                if ($defdom eq '') {
+                    $defdom = $cdom;
+                }
             }
-            my $sellink = &Apache::loncommon::selectstudent_link('userview','vuname','vudom');
+            my $sellink = &Apache::loncommon::selectstudent_link('userview','vuname','vudom','','','vuidentifier');
             my $selscript=&Apache::loncommon::studentbrowser_javascript();
             my $shownsymb = &HTML::Entities::encode(&Apache::lonenc::check_encrypt($env{'request.symb'}),'<>&"');
-            my $input = &mt('User: [_1] or ID: [_2] at: [_3]',
-                            '<input name="vuname" type="text" size="8" value="'.$vuname.'" />',
-                            '<input name="vid" type="text" size="8" value="'.$vid.'" />',
-                            &Apache::loncommon::select_dom_form($defdom,'vudom')).
-                            '<input name="LC_viewas" type="hidden" value="'.$viewas.'" />',
-                            '<input name="symb" type="hidden" value="'.$shownsymb.'" />';
+            my $input;
+            my @items = (
+                         '<label><input type="radio" name="vuidentifier" value="uname" checked="checked" onclick="javascript:toggleIdentifier(this.form);" />',
+                         '</label><input name="vuname" type="text" size="6" value="'.$vuname.'" id="LC_vuname" />',
+                         '<label><input type="radio" name="vuidentifier" value="uid" onclick="javascript:toggleIdentifier(this.form);" />',
+                         '</label><input name="vid" type="hidden" size="6" value="'.$vid.'" id="LC_vid" />'
+                        );
+            if ($domselector) {
+                push(@items,$domselector);
+                $input = &mt('[_1]User:[_2] or [_3]ID:[_4] at [_5] | ',@items);
+            } else {
+                $input = &mt('[_1]Username:[_2] or [_3]ID:[_4] | ',@items).
+                         '<input name="vudom" type="hidden" value="'.$defdom.'" />';
+            }
+            $input .= '<input name="LC_viewas" type="hidden" value="'.$viewas.'" />',
+                      '<input name="symb" type="hidden" value="'.$shownsymb.'" />';
             my $chooser = <<END;
 $selscript
 <a href="javascript:toggleViewAsUser('$change');" class="LC_menubuttons_link">
@@ -1130,8 +1235,8 @@ END
 # End course context
 
 # Prepare the rest of the buttons
-        my ($menuitems,$got_prt,$got_wishlist);
-        if ($const_space) {
+    my ($menuitems,$got_prt,$got_wishlist,$crsauthor,$toplevel_cstr,$crsauthor_cstr);
+    if ($const_space) {
 #
 # We are in construction space
 #
@@ -1139,15 +1244,15 @@ END
             my $londocroot = $Apache::lonnet::perlvar{'lonDocRoot'};
 	    my ($udom,$uname,$thisdisfn) =
 		($env{'request.filename'}=~m{^\Q$londocroot/priv/\E([^/]+)/([^/]+)/(.*)$});
+            if (($env{'request.course.id'}) &&
+                ($env{'course.'.$env{'request.course.id'}.'.num'} eq $uname) &&
+                ($env{'course.'.$env{'request.course.id'}.'.domain'} eq $udom)) {
+                $crsauthor_cstr = 1;
+            }
             my $currdir = '/priv/'.$udom.'/'.$uname.'/'.$thisdisfn;
             if ($currdir =~ m-/$-) {
-                $is_const_dir = 1;
                 if ($thisdisfn eq '') {
-                    unless (($env{'request.course.id'}) && 
-                            ($env{'course.'.$env{'request.course.id'}.'.num'} eq $uname) &&
-                            ($env{'course.'.$env{'request.course.id'}.'.domain'} eq $udom)) { 
-                        $is_const_dir = 2;
-                    }
+                    $toplevel_cstr = 1;
                 }
                 my $esc_currdir = &Apache::loncommon::escape_single($currdir);
                 $menuitems=(<<ENDMENUITEMS);
@@ -1156,6 +1261,13 @@ s&7&4&docs-22x22.png&Edit Metadata&defau
 s&7&2&prt.png&Print&printout[_1]&gocstr('/adm/printout','$esc_currdir')&Print contents of directory
 s&7&1&del.png&Delete&dir[_3]&gocstr('/adm/cfile?action=delete','$esc_currdir')&Delete this Directory
 ENDMENUITEMS
+                unless ($crsauthor_cstr) {
+                    if ($env{'environment.authorarchive'}) {
+                        $menuitems .= (<<ENDMENUITEMS);
+s&7&7&archive.png&Export&dir[_1]&gocstr('/adm/cfile?action=archive','$esc_currdir')&Export Authoring Space Archive
+ENDMENUITEMS
+                    }
+                }
             } else {
                 $currdir =~ s|[^/]+$||;
 		my $cleandisfn = &Apache::loncommon::escape_single($thisdisfn);
@@ -1170,12 +1282,19 @@ ENDMENUITEMS
 #
 # Probably should be in mydesk.tab
 #
-                $menuitems=(<<ENDMENUITEMS);
+                if (($crsauthor_cstr) && ($pubfile eq "/res/$udom/$uname/default.rights")) {
+                    $menuitems=(<<ENDMENUITEMS);
+s&6&1&list.png&Directory&dir[_1]&golist('$esc_currdir')&List current directory
+s&6&3&pub.png&Publish&resource[_3]&gocstr('/adm/publish','/priv/$udom/$uname/$cleandisfn')&Publish this resource
+ENDMENUITEMS
+                } else {
+                    $menuitems=(<<ENDMENUITEMS);
 s&6&1&list.png&Directory&dir[_1]&golist('$esc_currdir')&List current directory
 s&6&2&rtrv.png&Retrieve&version[_1]&gocstr('/adm/retrieve','/priv/$udom/$uname/$cleandisfn')&Retrieve old version
 s&6&3&pub.png&Publish&resource[_3]&gocstr('/adm/publish','/priv/$udom/$uname/$cleandisfn')&Publish this resource
 s&7&3&copy.png&Copy&resource[_4]&gocstr('/adm/cfile?action=copy','/priv/$udom/$uname/$cleandisfn')&Copy this resource
 ENDMENUITEMS
+                }
 #
 # Rename and Delete only available if obsolete or unpublished
 #
@@ -1185,9 +1304,42 @@ s&7&4&rename.png&Rename&resource[_5]&goc
 s&7&1&del.png&Delete&resource[_2]&gocstr('/adm/cfile?action=delete','/priv/$udom/$uname/$cleandisfn')&Delete this resource
 ENDMENUITEMS
                 }
-                $menuitems .= (<<ENDMENUITEMS);
+#
+# Print only makes sense for certain mime types
+#
+                if ($thisdisfn=~/\.(xml|html|htm|xhtml|xhtm|tex)$/ || $thisdisfn=~/$LONCAPA::assess_re/) {
+                    $menuitems .= (<<ENDMENUITEMS);
 s&7&2&prt.png&Print&printout[_1]&gocstr('/adm/printout','/priv/$udom/$uname/$cleandisfn')&Prepare a printable document
 ENDMENUITEMS
+                }
+#
+# "Exit Daxe" in Functions menu when using Daxe
+#
+                if ((($env{'form.editmode'} eq 'daxe') &&
+                     ($thisdisfn=~/\.(xml|html|htm|xhtml|xhtm)$/)) ||
+                    (($env{'form.problemmode'} eq 'daxe') &&
+                     ($thisdisfn=~/$LONCAPA::assess_re/))) {
+                    my %editors = &Apache::loncommon::permitted_editors();
+                    if ($editors{'daxe'}) {
+                        my $privfile = &Apache::loncommon::escape_single("/priv/$udom/$uname/$thisdisfn");
+                        $in_daxe = 1;
+                        $menuitems .= (<<ENDMENUITEMS);
+my $privfile = &Apache::loncommon::escape_single("/priv/$udom/$uname/$thisdisfn");
+s&7&6&tolastloc.png&Exit Daxe&resource[_1]&go('$privfile')&Exit editing this resource
+ENDMENUITEMS
+                    }
+                }
+            }
+#
+# Editing options usually accessed via "Settings" in inline menu need to be
+# accessed in a different way, when Authoring Space is accessed in course
+# context
+#
+            if ($env{'request.role'} !~/^(aa|ca|au)/) {
+                my $privfile = &Apache::loncommon::escape_single("/priv/$udom/$uname/$thisdisfn");
+                $menuitems .= (<<ENDMENUITEMS);
+s&7&5&editops.png&Options&edit[_1]&gocstr('/adm/preferences?action=authorsettings','$privfile')&Authoring Space Options
+ENDMENUITEMS
             }
                 if (ref($bread_crumbs) eq 'ARRAY') {
                     &Apache::lonhtmlcommon::clear_breadcrumbs();
@@ -1261,8 +1413,12 @@ ENDMENUITEMS
             $got_prt = 1;
             if (($env{'user.adv'}) && ($env{'request.uri'} =~ /^\/res/)
                 && (!$env{'request.enc'})) {
-                my ($cnum,$cdom) = &Apache::loncommon::crsauthor_url($env{'request.uri'});
-                unless ($cnum) {
+                my $privurl = $env{'request.uri'};
+                $privurl =~ s{^/res/}{/priv/};
+                my ($cnum,$cdom) = &Apache::loncommon::crsauthor_url($privurl);
+                if ($cnum) {
+                    $crsauthor = 1;
+                } else {
                     # wishlist is only available for users with access to resource-pool
                     # and links can only be set for resources within the resource-pool
                     $menuitems .= (<<ENDMENUITEMS);
@@ -1317,7 +1473,7 @@ s&8&3&prt.png&Print&printout[_1]&gopost(
 ENDMENUITEMS
                 $got_prt = 1;
             }
-            unless ($got_wishlist) {
+            unless (($got_wishlist) || ($crsauthor)) {
                 if (($env{'user.adv'}) && (!$env{'request.enc'})) {
                     # wishlist is only available for users with access to resource-pool
                     $menuitems .= (<<ENDMENUITEMS);
@@ -1394,8 +1550,13 @@ ENDMENUITEMS
             &Apache::lonhtmlcommon::add_breadcrumb_tool(
                 'tools',@tools);
 
+            #exit editing link/icon when using daxe in construction space 
             #publish button in construction space
             if ($env{'request.state'} eq 'construct'){
+                if ($in_daxe) {
+                    &Apache::lonhtmlcommon::add_breadcrumb_tool(
+                         'advtools', $inlineremote[76]);
+                }
                 &Apache::lonhtmlcommon::add_breadcrumb_tool(
                      'advtools', $inlineremote[63]);
             } else {
@@ -1403,6 +1564,12 @@ ENDMENUITEMS
                      'tools', $inlineremote[63]);
             }
             &advtools_crumbs(@inlineremote);
+            #options link/icon in constructions space viewed with course role
+            if (($env{'request.state'} eq 'construct') &&
+                ($env{'request.role'} !~/^(aa|ca|au)/)) {
+                &Apache::lonhtmlcommon::add_breadcrumb_tool(
+                         'advtools', $inlineremote[75]);
+            }
         }
     } else {
         if ($showprogress) {
@@ -1413,7 +1580,7 @@ ENDMENUITEMS
         }
     }
     my ($topic_help,$topic_help_text);
-    if ($is_const_dir == 2) {
+    if ($toplevel_cstr && !$crsauthor_cstr) {
         if ((($ENV{'SERVER_PORT'} == 443) || 
              ($Apache::lonnet::protocol{$Apache::lonnet::perlvar{'lonHostID'}} eq 'https')) && 
             (&Apache::lonnet::usertools_access($env{'user.name'},$env{'user.domain'},'webdav'))) {
@@ -1503,20 +1670,40 @@ sub prepare_functions {
             $editbutton = &get_editbutton($cfile,$home,$switchserver,
                                           $forceedit,$forceview,$forcereg);
         }
-    } elsif ((!$env{'request.course.id'}) &&
-             ($env{'user.author'}) && ($env{'request.filename'}) &&
-             ($env{'request.role'} !~/^(aa|ca|au)/)) {
+    } elsif (!$env{'request.course.id'}) {
+        if (($env{'user.author'}) && ($resurl eq '/adm/viewcoauthors')) {
+            if ($env{'request.role'} =~/^(ca|au)/) {
+                my ($audom,$auname);
+                if ($env{'request.role'} eq "au./$env{'user.domain'}/") {
+                    ($audom,$auname) = ($env{'user.domain'},$env{'user.name'});
+                } elsif ($env{'request.role'} =~ m{^ca\./($match_domain)/($match_username)}) {
+                    ($audom,$auname) = ($1,$2);
+                }
+                if (($audom ne '') && ($auname ne '')) {
+                    my $file=&Apache::lonnet::declutter($env{'request.filename'});
+                    ($cfile,$home,$switchserver,$forceedit,$forceview) =
+                    &Apache::lonnet::can_edit_resource($file,$auname,$audom,
+                                                       $resurl);
+                    if ($cfile) {
+                        $editbutton = &get_editbutton($resurl,'','',$forceedit,
+                                                      $forceview);
+                    }
+                }
+            }
+        } elsif (($env{'user.author'}) && ($env{'request.filename'}) &&
+                 ($env{'request.role'} !~/^(aa|ca|au)/)) {
 #
 # Currently do not have the role of author or co-author.
 # Do we have authoring privileges for the resource?
 #
-        my $file=&Apache::lonnet::declutter($env{'request.filename'});
-        ($cfile,$home,$switchserver,$forceedit,$forceview) =
-            &Apache::lonnet::can_edit_resource($file,$cnum,$cdom,
-                &Apache::lonnet::clutter($resurl),$env{'request.symb'},$group);
-        if (($cfile) && ($home ne '') && ($home ne 'no_host')) {
-            $editbutton = &get_editbutton($cfile,$home,$switchserver,
-                                          $forceedit,$forceview,$forcereg);
+            my $file=&Apache::lonnet::declutter($env{'request.filename'});
+            ($cfile,$home,$switchserver,$forceedit,$forceview) =
+                &Apache::lonnet::can_edit_resource($file,$cnum,$cdom,
+                    &Apache::lonnet::clutter($resurl),$env{'request.symb'},$group);
+            if (($cfile) && ($home ne '') && ($home ne 'no_host')) {
+                $editbutton = &get_editbutton($cfile,$home,$switchserver,
+                                              $forceedit,$forceview,$forcereg);
+            }
         }
     } elsif ($env{'request.course.id'}) {
 #
@@ -1567,7 +1754,14 @@ sub prepare_functions {
         } elsif (($resurl !~ m{^/?adm/($match_domain)/($match_username)/aboutme$}) &&
                  ($resurl ne '/cgi-bin/printout.pl')) {
             if ($env{'request.filename'}) {
-                my $file=&Apache::lonnet::declutter($env{'request.filename'});
+                my $file;
+                my $londocroot = $Apache::lonnet::perlvar{'lonDocRoot'};
+                if ($env{'request.filename'} =~ m{^\Q$londocroot\E/priv/}) {
+                    $file = $env{'request.filename'};
+                    $file =~ s{^\Q$londocroot\E/}{};
+                } else {
+                    $file=&Apache::lonnet::declutter($env{'request.filename'});
+                }
                 ($cfile,$home,$switchserver,$forceedit,$forceview) =
                     &Apache::lonnet::can_edit_resource($file,$cnum,$cdom,
                         &Apache::lonnet::clutter($resurl),$env{'request.symb'},$group);
@@ -1709,7 +1903,7 @@ sub advtools_crumbs {
     } elsif ($env{'request.noversionuri'} !~ m{^/adm/(navmaps|viewclasslist)(\?|$)}) {
         if ($env{'request.state'} eq 'construct') {
             &Apache::lonhtmlcommon::add_breadcrumb_tool(
-                'advtools', @funcs[61,73,74,71,72]);
+                'advtools', @funcs[61,73,74,71,72,77]);
         } else {
             &Apache::lonhtmlcommon::add_breadcrumb_tool(
                 'advtools', @funcs[61,71,72,73,74,75,92]);
@@ -1924,6 +2118,8 @@ sub rawconfig {
                 } else {
                     next;
                 }
+            } elsif ($priv eq 'cca') {
+                next if ($rol eq 'cm');
             }
             if ((($priv eq 'bre') && (&Apache::lonnet::allowed($priv,$prt) eq 'F')) ||
                 (($priv ne 'bre') && (&Apache::lonnet::allowed($priv,$prt)))) {
@@ -2005,6 +2201,24 @@ sub rawconfig {
                     }
                 }
             }
+        } elsif ($pro eq 'coauthor') {
+            if ($env{'request.role'}=~ m{^(ca|aa)\./($match_domain)/($match_username)$}) {
+                my ($role,$audom,$auname) = ($1,$2,$3);
+                if ((($prt eq 'raa') && ($role eq 'aa')) ||
+                    (($prt eq 'rca') && ($role eq 'ca') &&
+                     (!$env{"environment.internal.manager./$audom/$auname"}))) {
+                    $output.=&switch($auname,$audom,
+                                     $row,$col,$img,$top,$bot,$act,$desc,$cat);
+                }
+            }
+        } elsif ($pro eq 'coauthorenv_manager') {
+            if ($env{'request.role'}=~ m{^ca\./($match_domain)/($match_username)$}) {
+                my ($audom,$auname) = ($1,$2);
+                if ($env{"environment.internal.manager./$audom/$auname"}) {
+                    $output.=&switch($auname,$audom,
+                                     $row,$col,$img,$top,$bot,$act,$desc,$cat);
+                }
+            }
         } elsif ($pro eq 'tools') {
             my @tools = ('aboutme','blog','portfolio');
             if (grep(/^\Q$prt\E$/,@tools)) {
@@ -2336,23 +2550,28 @@ sub view_as_js {
     return <<"END";
 
 function toggleViewAsUser(change) {
-    var seluserid = document.getElementById('LC_selectuser');
-    var currstyle = seluserid.style.display;
-    if (change == 'off') {
-        document.userview.elements['LC_viewas'].value = '';
-        document.userview.elements['vuname'].value = '';
-        document.userview.elements['vid'].value = '';
-        document.userview.submit();
-        return;
-    }
-    if (currstyle == 'inline') {
-        seluserid.style.display = 'none';
-        document.getElementById('usexpand').innerHTML='&#9658;&nbsp;';
-        document.getElementById('uscollapse').innerHTML='';
-    } else {
-        seluserid.style.display = 'inline';
-        document.getElementById('usexpand').innerHTML='';
-        document.getElementById('uscollapse').innerHTML='&#9668;&nbsp;';
+    if (document.getElementById('LC_selectuser')) {
+        var seluserid = document.getElementById('LC_selectuser');
+        var currstyle = seluserid.style.display;
+        if (change == 'off') {
+            document.userview.elements['LC_viewas'].value = '';
+            document.userview.elements['vuname'].value = '';
+            document.userview.elements['vid'].value = '';
+            document.userview.submit();
+            return;
+        }
+        if ((document.getElementById('usexpand')) && (document.getElementById('uscollapse'))) {
+            if (currstyle == 'inline') {
+                seluserid.style.display = 'none';
+                document.getElementById('usexpand').innerHTML='&#9658;&nbsp;';
+                document.getElementById('uscollapse').innerHTML='';
+            } else {
+                seluserid.style.display = 'inline';
+                document.getElementById('usexpand').innerHTML='';
+                document.getElementById('uscollapse').innerHTML='&#9668;&nbsp;';
+                toggleIdentifier(document.userview);
+            }
+        }
     }
     return;
 }
@@ -2360,7 +2579,13 @@ function toggleViewAsUser(change) {
 function validCourseUser(form,change) {
     var possuname = form.elements['vuname'].value;
     var possuid = form.elements['vid'].value;
-    var possudom = form.elements['vudom'].options[form.elements['vudom'].selectedIndex].value;
+    var domelem = form.elements['vudom'];
+    var possudom = '';
+    if ((domelem.tagName === 'INPUT') && ((domelem.type === 'text') || (domelem.type === 'hidden'))) {
+        possudom = domelem.value;
+    } else if (domelem.tagName === 'SELECT') {
+        possudom = domelem.options[domelem.selectedIndex].value;
+    }
     if ((possuname == '') && (possuid == '')) {
         if (change == 'off') {
             form.elements['LC_viewas'].value = '';
@@ -2396,6 +2621,30 @@ function validCourseUser(form,change) {
     return false;
 }
 
+function toggleIdentifier(form) {
+    if ((document.getElementById('LC_vuname')) && (document.getElementById('LC_vid'))) {
+        var radioelem = form.elements['vuidentifier'];
+        if (radioelem.length > 0) {
+            var i;
+            for (i=0; i<radioelem.length; i++) {
+                if (radioelem[i].checked == true) {
+                    if (radioelem[i].value == 'uname') {
+                        document.getElementById('LC_vuname').type = 'text';
+                        document.getElementById('LC_vid').type = 'hidden';
+                        document.getElementById('LC_vid').value = '';
+                    } else {
+                        document.getElementById('LC_vuname').type = 'hidden';
+                        document.getElementById('LC_vuname').value = '';
+                        document.getElementById('LC_vid').type = 'text';
+                    }
+                    break;
+                }
+            }
+        }
+    }
+    return;
+}
+
 END
 }
 
@@ -2570,6 +2819,10 @@ function gocstr(url,filename) {
         this.document.cstrprint.submit();
         return;
     }
+    if (url == '/adm/preferences?action=authorsettings') {
+        document.location.href=url+'&returnurl='+filename;
+        return;
+    }
     if (url !='') {
         this.document.constspace.filename.value = filename;
         this.document.constspace.action = url;