--- loncom/interface/lonmenu.pm	2016/10/29 05:29:28	1.458
+++ loncom/interface/lonmenu.pm	2017/02/20 18:29:22	1.468
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Routines to control the menu
 #
-# $Id: lonmenu.pm,v 1.458 2016/10/29 05:29:28 raeburn Exp $
+# $Id: lonmenu.pm,v 1.468 2017/02/20 18:29:22 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -381,6 +381,7 @@ sub secondary_menu {
                                                ? "/$env{'request.course.sec'}"
                                                : '');
     my $canedit       = &Apache::lonnet::allowed('mdc', $env{'request.course.id'});
+    my $canvieweditor = &Apache::lonnet::allowed('cev', $env{'request.course.id'});
     my $canviewroster = $env{'course.'.$env{'request.course.id'}.'.student_classlist_view'};
     if ($canviewroster eq 'disabled') {
         undef($canviewroster);
@@ -400,7 +401,7 @@ sub secondary_menu {
     if ($env{'request.course.id'}) {
         $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
         $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
-        if ($canedit) {
+        if ($canedit || $canvieweditor)  {
             $showsyllabus = 1;
             $showfeeds = 1;
         } else {
@@ -416,7 +417,7 @@ sub secondary_menu {
                 $showfeeds = 1;
             }
         }
-        unless (($canmgr || $canvgr)) {
+        unless ($canmgr || $canvgr) {
             my %slots = &Apache::lonnet::get_course_slots($cnum,$cdom);
             if (keys(%slots) > 0) {
                 $showresv = 1;
@@ -452,8 +453,8 @@ sub secondary_menu {
         next if    $$menuitem[4]   ne 'always'
                 && ($$menuitem[4]   ne 'author' && $$menuitem[4] ne 'cca')
                 && !$env{'request.course.id'};
-        next if    $$menuitem[4]   =~ /^mdc/
-                && !$canedit;
+        next if    $$menuitem[4]   =~ /^crsedit/
+                && (!$canedit && !$canvieweditor);
         next if    $$menuitem[4]  eq 'nvgr'
                 && $canvgr;
         next if    $$menuitem[4]  eq 'vgr'
@@ -496,11 +497,21 @@ sub secondary_menu {
                 my $url = $$menuitem[0];
                 $url =~ s{\[cdom\]/\[cnum\]}{$cdom/$cnum};
                 if (&Apache::lonnet::is_on_map($url)) {
-                    unless ($$menuitem[0] =~ /\?register=1/) {
-                        $$menuitem[0] .= '?register=1';
+                    unless ($$menuitem[0] =~ /(\?|\&)register=1/) {
+                        $$menuitem[0] .= (($$menuitem[0]=~/\?/)? '&' : '?').'register=1';
                     }
                 } else {
-                    $$menuitem[0] =~ s{\?register=1}{};
+                    $$menuitem[0] =~ s{\&?register=1}{};
+                }
+                if ($env{'course.'.$env{'request.course.id'}.'.externalsyllabus'} =~ m{^http://}) {
+                    if (($ENV{'SERVER_PORT'} == 443) || ($env{'request.use_absolute'} =~ m{^https://})) {
+                        unless ($$menuitem[0] =~ m{^https?://}) {
+                            $$menuitem[0] = 'http://'.$ENV{'SERVER_NAME'}.$$menuitem[0];
+                        }
+                        unless ($$menuitem[0] =~ /(\&|\?)usehttp=1/) {
+                            $$menuitem[0] .= (($$menuitem[0]=~/\?/) ? '&' : '?').'usehttp=1';
+                        }
+                    }
                 }
             }
             $menu .= &prep_menuitem(\@$menuitem);
@@ -624,7 +635,7 @@ sub build_submenu {
 }
 
 sub innerregister {
-    my ($forcereg,$bread_crumbs,$group,$pagebuttonshide) = @_;
+    my ($forcereg,$bread_crumbs,$group,$pagebuttonshide,$hostname) = @_;
     my $const_space = ($env{'request.state'} eq 'construct');
     my $is_const_dir = 0;
 
@@ -691,7 +702,7 @@ sub innerregister {
                 }
                 my $trail;
                 if ($env{'form.folderpath'}) {
-                    &prepare_functions($resurl,$forcereg,$group,undef,undef,1);
+                    &prepare_functions($resurl,$forcereg,$group,undef,undef,1,$hostname);
                     ($trail) =
                         &Apache::lonhtmlcommon::docs_breadcrumbs(undef,$crstype,undef,$title,1);
                 } else {
@@ -706,10 +717,10 @@ sub innerregister {
             } elsif ($resurl =~ m{^\Q/uploaded$courseurl/portfolio/syllabus/}) {
                 &Apache::lonhtmlcommon::clear_breadcrumbs();
                 &prepare_functions('/public'.$courseurl."/syllabus",
-                                   $forcereg,$group,undef,undef,1);
+                                   $forcereg,$group,undef,undef,1,$hostname);
                 $title = &mt('Syllabus File');
                 my ($trail) =
-                    &Apache::lonhtmlcommon::docs_breadcrumbs(undef,$crstype,undef,$title,1);
+                    &Apache::lonhtmlcommon::docs_breadcrumbs(undef,$crstype,undef,$title,1,$hostname);
                 return $trail;
             }
             unless ($env{'request.state'} eq 'construct') {
@@ -733,7 +744,7 @@ sub innerregister {
         $forceview,$editbutton);
     if (($resurl =~ m{^/?adm/($match_domain)/($match_username)/aboutme$}) ||
         ($env{'request.role'} !~/^(aa|ca|au)/)) {
-        $editbutton = &prepare_functions($resurl,$forcereg,$group);
+        $editbutton = &prepare_functions($resurl,$forcereg,$group,'','','',$hostname);
     }
     if ($editbutton eq '') {
         $editbutton = &clear(6,1);
@@ -746,6 +757,7 @@ sub innerregister {
         $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
         $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
         $perms{'mdc'} = &Apache::lonnet::allowed('mdc',$env{'request.course.id'});
+        $perms{'cev'} = &Apache::lonnet::allowed('cev',$env{'request.course.id'});
         my @privs;
         if ($env{'request.symb'} ne '') {
              if ($env{'request.filename'}=~/$LONCAPA::assess_re/) {
@@ -785,7 +797,7 @@ sub innerregister {
 #
 # This applies to items inside a folder/page modifiable in the course.
 #
-        if (($env{'request.symb'}=~/^uploaded/) && ($perms{'mdc'})) {
+        if (($env{'request.symb'}=~/^uploaded/) && (($perms{'mdc'}) || ($perms{'cev'}))) {
             my $text = 'Edit Folder';
             if (($mapurl =~ /\.page$/) ||
                 ($env{'request.symb'}=~
@@ -1031,12 +1043,12 @@ ENDMENUITEMS
 }
 
 sub get_editbutton {
-    my ($cfile,$home,$switchserver,$forceedit,$forceview,$forcereg) = @_;
+    my ($cfile,$home,$switchserver,$forceedit,$forceview,$forcereg,$hostname) = @_;
     my $jscall;
     if (($forceview) && ($env{'form.todocs'})) {
-        my ($folderpath,$command);
+        my ($folderpath,$command,$navmap);
         if ($env{'request.symb'}) {
-            $folderpath = &Apache::loncommon::symb_to_docspath($env{'request.symb'});
+            $folderpath = &Apache::loncommon::symb_to_docspath($env{'request.symb'},\$navmap);
         } elsif ($env{'form.folderpath'} =~ /^supplemental/) {
             $folderpath = $env{'form.folderpath'};
             $command = '&forcesupplement=1';
@@ -1044,11 +1056,16 @@ sub get_editbutton {
         $folderpath = &escape(&HTML::Entities::encode(&escape($folderpath),'<>&"'));
         $jscall = "go('/adm/coursedocs?folderpath=$folderpath$command')";
     } else {
+        my $suppanchor;
+        if ($env{'form.folderpath'}) {
+            $suppanchor = $env{'form.anchor'};
+        }
         $jscall = &Apache::lonhtmlcommon::jump_to_editres($cfile,$home,$switchserver,
                                                 $forceedit,$forcereg,$env{'request.symb'},
                                                 &escape($env{'form.folderpath'}),
-                                                &escape($env{'form.title'}),$env{'form.idx'},
-                                                &escape($env{'form.suppurl'},$env{'form.todocs'}));
+                                                &escape($env{'form.title'}),$hostname,
+                                                $env{'form.idx'},&escape($env{'form.suppurl'}),
+                                                $env{'form.todocs'},$suppanchor);
     }
     if ($jscall) {
         my $icon = 'pcstr.png';
@@ -1065,7 +1082,7 @@ sub get_editbutton {
 }
 
 sub prepare_functions {
-    my ($resurl,$forcereg,$group,$bread_crumbs,$advtools,$docscrumbs) = @_;
+    my ($resurl,$forcereg,$group,$bread_crumbs,$advtools,$docscrumbs,$hostname) = @_;
     unless ($env{'request.registered'}) {
         undef(@inlineremote);
     }
@@ -1121,7 +1138,8 @@ sub prepare_functions {
                 $forceedit = 1;
             }
             $editbutton = &get_editbutton($cfile,$home,$switchserver,
-                                          $forceedit,$forceview,$forcereg);
+                                          $forceedit,$forceview,$forcereg,
+                                          $hostname);
         } elsif (($resurl eq '/adm/extresedit') &&
                  (($env{'form.symb'}) || ($env{'form.folderpath'}))) {
             ($cfile,$home,$switchserver,$forceedit,$forceview) =
@@ -1129,8 +1147,7 @@ sub prepare_functions {
                                                $env{'form.symb'});
             if ($cfile ne '') {
                 $editbutton = &get_editbutton($cfile,$home,$switchserver,
-                                              $forceedit,$forceview,$forcereg,
-                                              $env{'form.title'},$env{'form.suppurl'});
+                                              $forceedit,$forceview,$forcereg);
             }
         } elsif (($resurl =~ m{^/?adm/viewclasslist$}) &&
                  (&Apache::lonnet::allowed('opa',$env{'request.course.id'}))) {
@@ -1148,7 +1165,8 @@ sub prepare_functions {
                         &Apache::lonnet::clutter($resurl),$env{'request.symb'},$group);
                 if ($cfile ne '') {
                     $editbutton = &get_editbutton($cfile,$home,$switchserver,
-                                                  $forceedit,$forceview,$forcereg);
+                                                  $forceedit,$forceview,$forcereg,
+                                                  $hostname);
                 }
             }
         }
@@ -1205,10 +1223,18 @@ sub prepare_functions {
              ($resurl =~ m{^/adm/$match_domain/$match_username/aboutme$}))) {
             my @folders=split('&',$env{'form.folderpath'});
             if ((@folders > 2) || ($resurl ne '/adm/supplemental')) {
+                my $suppanchor;
+                if ($resurl =~ m{^/adm/wrapper/ext/}) {
+                    $suppanchor = $env{'form.anchor'};
+                }
                 my $esc_path=&escape(&HTML::Entities::encode(&escape($env{'form.folderpath'}),'<>&"'));
+                my $link = '/adm/coursedocs?command=direct&amp;forcesupplement=1&amp;supppath='.
+                           "$esc_path&amp;anchor=$suppanchor";
+                if ($env{'request.use_absolute'} ne '') {
+                    $link = $env{'request.use_absolute'}.$link;
+                }
                 &switch('','',7,4,'docs-22x22.png','Edit Folder','parms[_2]',
-                        "location.href='/adm/coursedocs?command=direct&amp;forcesupplement=1&amp;supppath=$esc_path'",
-                        'Folder/Page Content');
+                        "location.href='$link'",'Folder/Page Content');
             }
         }
     }
@@ -2088,7 +2114,7 @@ sub roles_selector {
     my ($cdom,$cnum,$httphost) = @_;
     my $crstype = &Apache::loncommon::course_type();
     my $now = time;
-    my (%courseroles,%seccount,%courseprivs);
+    my (%courseroles,%seccount,%courseprivs,%roledesc);
     my $is_cc;
     my ($js,$form,$switcher);
     my $ccrole;
@@ -2099,11 +2125,11 @@ sub roles_selector {
     }
     my ($privref,$gotsymb,$destsymb);
     my $destinationurl = $ENV{'REQUEST_URI'};
-    if ($destinationurl =~ /\?symb=/) {
+    if ($destinationurl =~ /(\?|\&)symb=/) {
         $gotsymb = 1;
     } elsif ($destinationurl =~ m{^/enc/}) {
         my $plainurl = &Apache::lonenc::unencrypted($destinationurl);
-        if ($plainurl =~ /\?symb=/) {
+        if ($plainurl =~ /(\?|\&)symb=/) {
             $gotsymb = 1;
         }
     }
@@ -2138,7 +2164,7 @@ sub roles_selector {
     if ($is_cc) {
         &get_all_courseroles($cdom,$cnum,\%courseroles,\%seccount,\%courseprivs);
     } elsif ($env{'request.role'} =~ m{^\Qcr/$cdom/$cdom-domainconfig/\E(\w+)\.\Q/$cdom/$cnum\E}) {
-        &get_customadhoc_roles($cdom,$cnum,\%courseroles,\%seccount,\%courseprivs,$privref);
+        &get_customadhoc_roles($cdom,$cnum,\%courseroles,\%seccount,\%courseprivs,\%roledesc,$privref);
     } else {
         my %gotnosection;
         foreach my $item (keys(%env)) {
@@ -2192,7 +2218,7 @@ sub roles_selector {
     }
     if ((keys(%seccount) > 1) || ($numdiffsec > 1)) {
         my @submenu;
-        $js = &jump_to_role($cdom,$cnum,\%seccount,\%courseroles,\%courseprivs,$privref);
+        $js = &jump_to_role($cdom,$cnum,\%seccount,\%courseroles,\%courseprivs,\%roledesc,$privref);
         $form = 
             '<form name="rolechooser" method="post" action="'.$httphost.'/adm/roles">'."\n".
             '  <input type="hidden" name="destinationurl" value="'.
@@ -2232,8 +2258,17 @@ sub roles_selector {
                     $include = 1; 
                 }
                 if ($include) {
+                    my $rolename;
+                    if ($role =~ m{^cr/$cdom/$cdom\-domainconfig/(\w+)(?:/\w+|$)}) {
+                        $rolename = $roledesc{$role};
+                        if ($rolename eq '') {
+                            $rolename = &mt('Helpdesk [_1]',$1);
+                        }
+                    } else {
+                        $rolename = &Apache::lonnet::plaintext($role);
+                    }
                     push(@submenu,['javascript:adhocRole('."'$role'".')',
-                                   &Apache::lonnet::plaintext($role)]);
+                                   $rolename]);
                 }
             }
         }
@@ -2315,73 +2350,91 @@ sub get_all_courseroles {
 }
 
 sub get_customadhoc_roles {
-    my ($cdom,$cnum,$courseroles,$seccount,$courseprivs,$privref) = @_;
+    my ($cdom,$cnum,$courseroles,$seccount,$courseprivs,$roledesc,$privref) = @_;
     unless ((ref($courseroles) eq 'HASH') && (ref($seccount) eq 'HASH') &&
-            (ref($courseprivs) eq 'HASH')) {
+            (ref($courseprivs) eq 'HASH') && (ref($roledesc) eq 'HASH')) {
         return;
     }
-    if ($env{'environment.adhocroles.'.$cdom} ne '') { 
-        my @customroles = split(/,/,$env{'environment.adhocroles.'.$cdom});
-        if (@customroles > 1) {
-            if ($env{"user.role.dh./$cdom/"}) {
-                my ($start,$end)=split(/\./,$env{"user.role.dh./$cdom/"});
-                my $now = time; 
-                if (!($start && ($now<$start)) & !($end && ($now>$end))) {
-                    my $numsec = 1;
-                    my @sections;
-                    my ($allseclist,$cached) =
-                        &Apache::lonnet::is_cached_new('courseseclist',$cdom.'_'.$cnum);
-                    if (defined($cached)) {
-                        if ($allseclist ne '') {
-                            @sections = split(/,/,$allseclist);
-                            $numsec += scalar(@sections);
-                        }
-                    } else {
-                        my %sections_count = &Apache::loncommon::get_sections($cdom,$cnum);
-                        $numsec += scalar(keys(%sections_count));
-                        $allseclist = join(',',sort(keys(%sections_count)));
-                        &Apache::lonnet::do_cache_new('courseseclist',$cdom.'_'.$cnum,$allseclist);
-                    }
-                    my (%adhoc,$gotprivs);
-                    my $prefix = "cr/$cdom/$cdom".'-domainconfig';
-                    foreach my $role (@customroles) {
-                        next if (($role eq '') || ($role =~ /\W/));
-                        $seccount->{"$prefix/$role"} = $numsec;
-                        $courseroles->{"$prefix/$role"} = \@sections;
-                        if ((ref($privref) eq 'ARRAY') && (@{$privref} > 0)) {
-                            if (exists($env{"user.priv.$prefix/$role./$cdom/$cnum./"})) {
-                                $courseprivs->{"$prefix/$role./$cdom/$cnum./"} =
-                                    $env{"user.priv.$prefix/$role./$cdom/$cnum./"};
-                                $courseprivs->{"$prefix/$role./$cdom/$cnum./$cdom/"} =
-                                    $env{"user.priv.$prefix/$role./$cdom/$cnum./$cdom/"};
-                                $courseprivs->{"$prefix/$role./$cdom/$cnum./$cdom/$cnum"} =
-                                    $env{"user.priv.$prefix/$role./$cdom/$cnum./$cdom/$cnum"};
-                            } else {
-                                unless ($gotprivs) {
-                                    my ($adhocroles,$privscached) =
-                                        &Apache::lonnet::is_cached_new('adhocroles',$cdom);
-                                    if ((defined($privscached)) && (ref($adhocroles) eq 'HASH')) {
-                                        %adhoc = %{$adhocroles};
-                                    } else {
-                                        my $confname = &Apache::lonnet::get_domainconfiguser($cdom);
-                                        my %roledefs = &Apache::lonnet::dump('roles',$cdom,$confname,'rolesdef_');
-                                        foreach my $key (keys(%roledefs)) {
-                                            (undef,my $rolename) = split(/_/,$key);
-                                            if ($rolename ne '') {
-                                                $adhoc{$rolename} = $roledefs{$key};
-                                            }
+    my $is_helpdesk = 0;
+    my $now = time;
+    foreach my $role ('dh','da') {
+        if ($env{"user.role.$role./$cdom/"}) {
+            my ($start,$end)=split(/\./,$env{"user.role.$role./$cdom/"});
+            if (!($start && ($now<$start)) && !($end && ($now>$end))) {
+                $is_helpdesk = 1;
+                last;
+            }
+        }
+    }
+    if ($is_helpdesk) {
+        my ($possroles,$description) = &Apache::lonnet::get_my_adhocroles($cdom.'_'.$cnum);
+        my %available;
+        if (ref($possroles) eq 'ARRAY') {
+            map { $available{$_} = 1; } @{$possroles};
+        }
+        my %domdefaults = &Apache::lonnet::get_domain_defaults($cdom);
+        if (ref($domdefaults{'adhocroles'}) eq 'HASH') {
+            if (keys(%{$domdefaults{'adhocroles'}})) {
+                my $numsec = 1;
+                my @sections;
+                my ($allseclist,$cached) =
+                    &Apache::lonnet::is_cached_new('courseseclist',$cdom.'_'.$cnum);
+                if (defined($cached)) {
+                    if ($allseclist ne '') {
+                        @sections = split(/,/,$allseclist);
+                        $numsec += scalar(@sections);
+                    }
+                } else {
+                    my %sections_count = &Apache::loncommon::get_sections($cdom,$cnum);
+                    @sections = sort(keys(%sections_count));
+                    $numsec += scalar(@sections);
+                    $allseclist = join(',',@sections);
+                    &Apache::lonnet::do_cache_new('courseseclist',$cdom.'_'.$cnum,$allseclist);
+                }
+                my (%adhoc,$gotprivs);
+                my $prefix = "cr/$cdom/$cdom".'-domainconfig';
+                foreach my $role (keys(%{$domdefaults{'adhocroles'}})) {
+                    next if (($role eq '') || ($role =~ /\W/));
+                    $seccount->{"$prefix/$role"} = $numsec;
+                    $roledesc->{"$prefix/$role"} = $description->{$role};
+                    if ((ref($privref) eq 'ARRAY') && (@{$privref} > 0)) {
+                        if (exists($env{"user.priv.$prefix/$role./$cdom/$cnum./"})) {
+                            $courseprivs->{"$prefix/$role./$cdom/$cnum./"} =
+                                $env{"user.priv.$prefix/$role./$cdom/$cnum./"};
+                            $courseprivs->{"$prefix/$role./$cdom/$cnum./$cdom/"} =
+                                $env{"user.priv.$prefix/$role./$cdom/$cnum./$cdom/"};
+                            $courseprivs->{"$prefix/$role./$cdom/$cnum./$cdom/$cnum"} =
+                                $env{"user.priv.$prefix/$role./$cdom/$cnum./$cdom/$cnum"};
+                        } else {
+                            unless ($gotprivs) {
+                                my ($adhocroles,$privscached) =
+                                    &Apache::lonnet::is_cached_new('adhocroles',$cdom);
+                                if ((defined($privscached)) && (ref($adhocroles) eq 'HASH')) {
+                                    %adhoc = %{$adhocroles};
+                                } else {
+                                    my $confname = &Apache::lonnet::get_domainconfiguser($cdom);
+                                    my %roledefs = &Apache::lonnet::dump('roles',$cdom,$confname,'rolesdef_');
+                                    foreach my $key (keys(%roledefs)) {
+                                        (undef,my $rolename) = split(/_/,$key);
+                                        if ($rolename ne '') {
+                                            my ($systempriv,$domainpriv,$coursepriv) = split(/\_/,$roledefs{$key});
+                                            $coursepriv = &Apache::lonnet::course_adhocrole_privs($rolename,$cdom,$cnum,$coursepriv);
+                                            $adhoc{$rolename} = join('_',($systempriv,$domainpriv,$coursepriv));
                                         }
-                                        &Apache::lonnet::do_cache_new('adhocroles',$cdom,\%adhoc);
                                     }
-                                    $gotprivs = 1;
+                                    &Apache::lonnet::do_cache_new('adhocroles',$cdom,\%adhoc);
                                 }
-                                ($courseprivs->{"$prefix/$role./$cdom/$cnum./"},
-                                 $courseprivs->{"$prefix/$role./$cdom/$cnum./$cdom/"},
-                                 $courseprivs->{"$prefix/$role./$cdom/$cnum./$cdom/$cnum"}) =
-                                     split(/\_/,$adhoc{$role});
+                                $gotprivs = 1;
                             }
+                            ($courseprivs->{"$prefix/$role./$cdom/$cnum./"},
+                             $courseprivs->{"$prefix/$role./$cdom/$cnum./$cdom/"},
+                             $courseprivs->{"$prefix/$role./$cdom/$cnum./$cdom/$cnum"}) =
+                                 split(/\_/,$adhoc{$role});
                         }
                     }
+                    if ($available{$role}) {
+                        $courseroles->{"$prefix/$role"} = \@sections;
+                    }
                 }
             }
         }
@@ -2390,7 +2443,7 @@ sub get_customadhoc_roles {
 }
 
 sub jump_to_role {
-    my ($cdom,$cnum,$seccount,$courseroles,$courseprivs,$privref) = @_;
+    my ($cdom,$cnum,$seccount,$courseroles,$courseprivs,$roledesc,$privref) = @_;
     my %lt = &Apache::lonlocal::texthash(
                 this => 'This role has section(s) associated with it.',
                 ente => 'Enter a specific section.',
@@ -2542,7 +2595,7 @@ sub required_privs {
              '/adm/parmset'      => 'opa,vpa',
              '/adm/courseprefs'  => 'opa,vpa',
              '/adm/whatsnew'     => 'whn',
-             '/adm/populate'     => 'cst',
+             '/adm/populate'     => 'cst,vpa,vcl',
              '/adm/trackstudent' => 'vsa',
              '/adm/statistics'   => 'mgr,vgr',
              '/adm/setblock'     => 'dcm,vcb',