--- loncom/xml/lonxml.pm 2004/03/31 05:24:00 1.315 +++ loncom/xml/lonxml.pm 2004/12/03 22:14:22 1.349 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # XML Parser Module # -# $Id: lonxml.pm,v 1.315 2004/03/31 05:24:00 albertel Exp $ +# $Id: lonxml.pm,v 1.349 2004/12/03 22:14:22 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -36,30 +36,11 @@ # The C source of the Code may not be distributed by the Licensee # to any other parties under any circumstances. # -# last modified 06/26/00 by Alexander Sakharuk -# 11/6 Gerd Kortemeyer -# 6/1/1 Gerd Kortemeyer -# 2/21,3/13 Guy -# 3/29,5/4 Gerd Kortemeyer -# 5/26 Gerd Kortemeyer -# 5/27 H. K. Ng -# 6/2,6/3,6/8,6/9 Gerd Kortemeyer -# 6/12,6/13 H. K. Ng -# 6/16 Gerd Kortemeyer -# 7/27 H. K. Ng -# 8/7,8/9,8/10,8/11,8/15,8/16,8/17,8/18,8/20,8/23,8/24 Gerd Kortemeyer -# Guy Albertelli -# 9/26 Gerd Kortemeyer -# Dec Guy Albertelli -# YEAR=2002 -# 1/1 Gerd Kortemeyer -# 1/2 Matthew Hall -# 1/3 Gerd Kortemeyer -# + package Apache::lonxml; use vars -qw(@pwd @outputstack $redirection $import @extlinks $metamode $evaluate %insertlist @namespace $errorcount $warningcount); +qw(@pwd @outputstack $redirection $import @extlinks $metamode $evaluate %insertlist @namespace $errorcount $warningcount @htmlareafields); use strict; use HTML::LCParser(); use HTML::TreeBuilder(); @@ -70,7 +51,7 @@ use Math::Cephes(); use Math::Random(); use Opcode(); use POSIX qw(strftime); - +use Time::HiRes qw( gettimeofday tv_interval ); sub register { my ($space,@taglist) = @_; @@ -169,6 +150,7 @@ $Apache::lonxml::warnings_error_header=' sub xmlbegin { my $output=''; + @htmlareafields=(); if ($ENV{'browser.mathml'}) { $output='' .'' @@ -177,19 +159,28 @@ sub xmlbegin { .''; } else { - $output=''; + $output=' +'; } return $output; } sub xmlend { + my ($target,$parser)=@_; my $mode='xml'; my $status='OPEN'; if ($Apache::lonhomework::parsing_a_problem) { $mode='problem'; $status=$Apache::inputtags::status[-1]; } - return &Apache::lonfeedback::list_discussion($mode,$status).''; + my $discussion=&Apache::lonfeedback::list_discussion($mode,$status); + if ($target eq 'tex') { + $discussion.='\keephidden{ENDOFPROBLEM}\vskip 0.5mm\noindent\makebox[\textwidth/$number_of_columns][b]{\hrulefill}\end{document}'; + &Apache::lonxml::newparser($parser,\$discussion,''); + return ''; + } else { + return $discussion.''; + } } sub tokeninputfield { @@ -297,7 +288,7 @@ sub fontsettings() { my $headerstring=''; if (($ENV{'browser.os'} eq 'mac') && (!$ENV{'browser.mathml'})) { $headerstring.= - ''; + ''; } elsif (!$ENV{'browser.mathml'} && $ENV{'browser.unicode'}) { $headerstring.= ''; @@ -330,13 +321,15 @@ sub xmlparse { my $bodytext= $ENV{'course.'.$ENV{'request.course.id'}.'.default_xml_style'}; if ($bodytext) { - my $location=&Apache::lonnet::filelocation('',$bodytext); - my $styletext=&Apache::lonnet::getfile($location); - if ($styletext ne '-1') { - %style_for_target = (%style_for_target, - &Apache::style::styleparser($target,$styletext)); - } - } + foreach my $file (split(',',$bodytext)) { + my $location=&Apache::lonnet::filelocation('',$file); + my $styletext=&Apache::lonnet::getfile($location); + if ($styletext ne '-1') { + %style_for_target = (%style_for_target, + &Apache::style::styleparser($target,$styletext)); + } + } + } } elsif ($ENV{'construct.style'} && ($ENV{'request.state'} eq 'construct')) { my $location=&Apache::lonnet::filelocation('',$ENV{'construct.style'}); my $styletext=&Apache::lonnet::getfile($location); @@ -407,8 +400,10 @@ sub latex_special_symbols { } else { $string=~s/\\/\\ensuremath{\\backslash}/g; $string=~s/([^\\]|^)\%/$1\\\%/g; - $string=~s/([^\\]|^)(\$|_)/$1\\$2/g; + $string=~s/([^\\]|^)\$/$1\\\$/g; + $string=~s/([^\\])\_/$1\\_/g; $string=~s/\$\$/\$\\\$/g; + $string=~s/\_\_/\_\\\_/g; $string=~s/\#\#/\#\\\#/g; $string=~s/([^\\]|^)(\~|\^)/$1\\$2\\strut /g; $string=~s/(>|<)/\\ensuremath\{$1\}/g; #more or less @@ -416,6 +411,7 @@ sub latex_special_symbols { # any & or # leftover should be safe to just escape $string=~s/([^\\]|^)\&/$1\\\&/g; $string=~s/([^\\]|^)\#/$1\\\#/g; + $string=~s/\|/\$\\mid\$/g; #single { or } How to escape? } return $string; @@ -479,7 +475,7 @@ sub inner_xmlparse { #clear out any tags that didn't end while ($token->[1] ne $$stack['-1'] && ($#$stack > -1)) { my $lasttag=$$stack[-1]; - if ($token->[1] =~ /^$lasttag$/i) { + if ($token->[1] =~ /^\Q$lasttag\E$/i) { &Apache::lonxml::warning('Using tag </'.$token->[1].'> on line '.$token->[3].' as end tag to <'.$$stack[-1].'>'); last; } else { @@ -543,6 +539,10 @@ sub inner_xmlparse { return $finaloutput; } +## +## Looks to see if there is a subroutine defined for this tag. If so, call it, +## otherwise do not call it as we do not know what it is. +## sub callsub { my ($sub,$target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; my $currentstring=''; @@ -575,6 +575,10 @@ sub callsub { $parstack,$parser,$safeeval, $style); } else { + if ($target eq 'tex') { + # throw away tag name + return ''; + } #&Apache::lonxml::debug("NOT Calling sub $sub in $space $metamode"); if ($metamode <1) { if (defined($token->[4]) && ($metamode < 1)) { @@ -615,6 +619,7 @@ sub setup_globals { my ($request,$target)=@_; $Apache::lonxml::request=$request; $Apache::lonxml::registered = 0; + @Apache::lonxml::htmlareafields=(); $errorcount=0; $warningcount=0; $Apache::lonxml::default_homework_loaded=0; @@ -673,7 +678,9 @@ sub init_safespace { $safehole->wrap(\&Apache::scripttag::xmlparse,$safeeval,'&xmlparse'); $safehole->wrap(\&Apache::outputtags::multipart,$safeeval,'&multipart'); $safehole->wrap(\&Apache::lonnet::EXT,$safeeval,'&EXT'); - + $safehole->wrap(\&Apache::chemresponse::chem_standard_order,$safeeval, + '&chem_standard_order'); + $safehole->wrap(\&Math::Cephes::asin,$safeeval,'&asin'); $safehole->wrap(\&Math::Cephes::acos,$safeeval,'&acos'); $safehole->wrap(\&Math::Cephes::atan,$safeeval,'&atan'); @@ -747,38 +754,19 @@ sub init_safespace { $safehole->wrap(\&Math::Random::random_set_seed,$safeeval,'&random_set_seed'); $safehole->wrap(\&Apache::lonxml::error,$safeeval,'&LONCAPA_INTERNAL_ERROR'); $safehole->wrap(\&Apache::lonxml::debug,$safeeval,'&LONCAPA_INTERNAL_DEBUG'); + $safehole->wrap(\&Apache::caparesponse::get_sigrange,$safeeval,'&LONCAPA_INTERNAL_get_sigrange'); #need to inspect this class of ops # $safeeval->deny(":base_orig"); + $safeeval->permit("require"); $safeinit .= ';$external::target="'.$target.'";'; my $rndseed; my ($symb,$courseid,$domain,$name) = &Apache::lonxml::whichuser(); $rndseed=&Apache::lonnet::rndseed($symb,$courseid,$domain,$name); - $safeinit .= ';$external::randomseed='.$rndseed.';'; + $safeinit .= ';$external::randomseed="'.$rndseed.'";'; &Apache::lonxml::debug("Setting rndseed to $rndseed"); &Apache::run::run($safeinit,$safeeval); - my $subroutine=<<'EVALUATESUB'; -sub __LC_INTERNAL_EVALUATE__ { - my ($__LC__a,$__LC__b,$__LC__c)=@_; - my $__LC__prefix; - while(1){ - { - use strict; - no strict "vars"; - if (eval(defined(eval($__LC__a.$__LC__b)))) { - return $__LC__prefix.eval($__LC__a.$__LC__b.$__LC__c); - } - } - $__LC__prefix.=substr($__LC__a,0,1,""); - if ($__LC__a!~/^(\$|&|\#)/) { last; } - } - return $__LC__prefix.$__LC__a.$__LC__b.$__LC__c; -} -EVALUATESUB - $safeeval->permit("require"); - $safeeval->reval($subroutine); - $safeeval->deny("require"); } sub default_homework_load { @@ -793,18 +781,26 @@ sub default_homework_load { } } +my $metamode_was; sub startredirection { - $Apache::lonxml::redirection++; - push (@Apache::lonxml::outputstack, ''); + if (!$Apache::lonxml::redirection) { + $metamode_was=$Apache::lonxml::metamode; + } + $Apache::lonxml::metamode=0; + $Apache::lonxml::redirection++; + push (@Apache::lonxml::outputstack, ''); } sub endredirection { - if (!$Apache::lonxml::redirection) { - &Apache::lonxml::error("Endredirection was called, before a startredirection, perhaps you have unbalanced tags. Some debuging information:".join ":",caller); - return ''; - } - $Apache::lonxml::redirection--; - pop @Apache::lonxml::outputstack; + if (!$Apache::lonxml::redirection) { + &Apache::lonxml::error("Endredirection was called, before a startredirection, perhaps you have unbalanced tags. Some debuging information:".join ":",caller); + return ''; + } + $Apache::lonxml::redirection--; + if (!$Apache::lonxml::redirection) { + $Apache::lonxml::metamode=$metamode_was; + } + pop @Apache::lonxml::outputstack; } sub end_tag { @@ -820,6 +816,8 @@ sub initdepth { $Apache::lonxml::olddepth=-1; } +my @timers; +my $lasttime; sub increasedepth { my ($token) = @_; $Apache::lonxml::depth++; @@ -827,8 +825,15 @@ sub increasedepth { if ($Apache::lonxml::depthcounter[$Apache::lonxml::depth]==1) { $Apache::lonxml::olddepth=$Apache::lonxml::depth; } + my $time; + if ($Apache::lonxml::debug eq "1") { + push(@timers,[&gettimeofday()]); + $time=&tv_interval($lasttime); + $lasttime=[&gettimeofday()]; + } + my $spacing=' 'x($Apache::lonxml::depth-1); my $curdepth=join('_',@Apache::lonxml::depthcounter); - &Apache::lonxml::debug("s $Apache::lonxml::depth : $Apache::lonxml::olddepth : $curdepth : $token->[1]\n"); + &Apache::lonxml::debug("s$spacing$Apache::lonxml::depth : $Apache::lonxml::olddepth : $curdepth : $token->[1] : $time : \n"); #print "
s $Apache::lonxml::depth : $Apache::lonxml::olddepth : $curdepth : $token->[1]\n"; } @@ -843,37 +848,44 @@ sub decreasedepth { &Apache::lonxml::warning(&mt("Missing tags, unable to properly run file.")); $Apache::lonxml::depth='-1'; } + my ($timer,$time); + if ($Apache::lonxml::debug eq "1") { + $timer=pop(@timers); + $time=&tv_interval($lasttime); + $lasttime=[&gettimeofday()]; + } + my $spacing=' 'x$Apache::lonxml::depth; my $curdepth=join('_',@Apache::lonxml::depthcounter); - &Apache::lonxml::debug("e $Apache::lonxml::depth : $Apache::lonxml::olddepth : $token->[1] : $curdepth\n"); + &Apache::lonxml::debug("e$spacing$Apache::lonxml::depth : $Apache::lonxml::olddepth : $curdepth : $token->[1] : $time : ".&tv_interval($timer)."\n"); #print "
e $Apache::lonxml::depth : $Apache::lonxml::olddepth : $token->[1] : $curdepth\n"; } sub get_all_text_unbalanced { #there is a copy of this in lonpublisher.pm - my($tag,$pars)= @_; - my $token; - my $result=''; - $tag='<'.$tag.'>'; - while ($token = $$pars[-1]->get_token) { - if (($token->[0] eq 'T')||($token->[0] eq 'C')||($token->[0] eq 'D')) { - $result.=$token->[1]; - } elsif ($token->[0] eq 'PI') { - $result.=$token->[2]; - } elsif ($token->[0] eq 'S') { - $result.=$token->[4]; - } elsif ($token->[0] eq 'E') { - $result.=$token->[2]; - } - if ($result =~ /(.*)\Q$tag\E(.*)/s) { - &Apache::lonxml::debug('Got a winner with leftovers ::'.$2); - &Apache::lonxml::debug('Result is :'.$1); - $result=$1; - my $redo=$tag.$2; - &Apache::lonxml::newparser($pars,\$redo); - last; - } - } - return $result + my($tag,$pars)= @_; + my $token; + my $result=''; + $tag='<'.$tag.'>'; + while ($token = $$pars[-1]->get_token) { + if (($token->[0] eq 'T')||($token->[0] eq 'C')||($token->[0] eq 'D')) { + $result.=$token->[1]; + } elsif ($token->[0] eq 'PI') { + $result.=$token->[2]; + } elsif ($token->[0] eq 'S') { + $result.=$token->[4]; + } elsif ($token->[0] eq 'E') { + $result.=$token->[2]; + } + if ($result =~ /\Q$tag\E/is) { + ($result,my $redo)=$result =~ /(.*)\Q$tag\E(.*)/is; + #&Apache::lonxml::debug('Got a winner with leftovers ::'.$2); + #&Apache::lonxml::debug('Result is :'.$1); + $redo=$tag.$redo; + &Apache::lonxml::newparser($pars,\$redo); + last; + } + } + return $result } sub increment_counter { @@ -926,12 +938,12 @@ sub get_all_text { } elsif ($token->[0] eq 'PI') { $result.=$token->[2]; } elsif ($token->[0] eq 'S') { - if ($token->[1] =~ /^$tag$/i) { $depth++; } - if ($token->[1] =~ /^LONCAPA_INTERNAL_TURN_STYLE_ON$/i) { $Apache::lonxml::usestyle=1; } - if ($token->[1] =~ /^LONCAPA_INTERNAL_TURN_STYLE_OFF$/i) { $Apache::lonxml::usestyle=0; } + if ($token->[1] =~ /^\Q$tag\E$/i) { $depth++; } + if ($token->[1] =~ /^LONCAPA_INTERNAL_TURN_STYLE_ON$/) { $Apache::lonxml::usestyle=1; } + if ($token->[1] =~ /^LONCAPA_INTERNAL_TURN_STYLE_OFF$/) { $Apache::lonxml::usestyle=0; } $result.=$token->[4]; } elsif ($token->[0] eq 'E') { - if ( $token->[1] =~ /^$tag$/i) { $depth--; } + if ( $token->[1] =~ /^\Q$tag\E$/i) { $depth--; } #skip sending back the last end tag if ($depth == 0 && exists($$style{'/'.$token->[1]}) && $Apache::lonxml::usestyle) { my $string= @@ -978,13 +990,13 @@ sub get_all_text { } elsif ($token->[0] eq 'PI') { $result.=$token->[2]; } elsif ($token->[0] eq 'S') { - if ( $token->[1] =~ /^$tag$/i) { + if ( $token->[1] =~ /^\Q$tag\E$/i) { $$pars[-1]->unget_token($token); last; } else { $result.=$token->[4]; } - if ($token->[1] =~ /^LONCAPA_INTERNAL_TURN_STYLE_ON$/i) { $Apache::lonxml::usestyle=1; } - if ($token->[1] =~ /^LONCAPA_INTERNAL_TURN_STYLE_OFF$/i) { $Apache::lonxml::usestyle=0; } + if ($token->[1] =~ /^LONCAPA_INTERNAL_TURN_STYLE_ON$/) { $Apache::lonxml::usestyle=1; } + if ($token->[1] =~ /^LONCAPA_INTERNAL_TURN_STYLE_OFF$/) { $Apache::lonxml::usestyle=0; } } elsif ($token->[0] eq 'E') { $result.=$token->[2]; } @@ -1017,6 +1029,8 @@ sub parstring { unless ($_=~/\W/) { my $val=$token->[2]->{$_}; $val =~ s/([\%\@\\\"\'])/\\$1/g; + $val =~ s/(\$[^{a-zA-Z_])/\\$1/g; + $val =~ s/(\$)$/\\$1/; #if ($val =~ m/^[\%\@]/) { $val="\\".$val; } $temp .= "my \$$_=\"$val\";"; } @@ -1066,7 +1080,7 @@ sub afterburn { my $anchorname=$_; my $matchthis=$anchorname; $matchthis=~s/\_+/\\s\+/g; - $result=~s/($matchthis)/\$1\<\/font\>/gs; + $result=~s/(\Q$matchthis\E)/\$1\<\/font\>/gs; } } if ($ENV{'form.link'}) { @@ -1074,14 +1088,14 @@ sub afterburn { my ($anchorname,$linkurl)=split(/\>/,$_); my $matchthis=$anchorname; $matchthis=~s/\_+/\\s\+/g; - $result=~s/($matchthis)/\$1\<\/a\>/gs; + $result=~s/(\Q$matchthis\E)/\$1\<\/a\>/gs; } } if ($ENV{'form.anchor'}) { my $anchorname=$ENV{'form.anchor'}; my $matchthis=$anchorname; $matchthis=~s/\_+/\\s\+/g; - $result=~s/($matchthis)/\$1\<\/a\>/s; + $result=~s/(\Q$matchthis\E)/\$1\<\/a\>/s; $result.=(<<"ENDSCRIPT"); +FULLPAGE + } else { + $initialize.=(< +$addbuttons + function initDocument() { + } + +FULLPAGE + } + $result=~s/\]*)\>/\/i; + $xml_help=&Apache::loncommon::helpLatexCheatsheet(); } my $cleanbut = ''; if ($filetype eq 'html') { @@ -1157,18 +1199,22 @@ $cleanbut BUTTONS + $buttons.=&Apache::lonhtmlcommon::spelllink('xmledit','filecont'); + $buttons.=&Apache::lonhtmlcommon::htmlareaselectactive('filecont'); my $editfooter=(< -
+ $xml_help $buttons
- +
$buttons
$titledisplay + ENDFOOTER # $result=~s/(\]*\>)/$1$editheader/is; $result=~s/(\<\/body\>)/$editfooter/is; @@ -1256,7 +1302,7 @@ $bodytag ENDNOTFOUND - $filecontents=''; + $filecontents=''; if ($ENV{'request.state'} ne 'published') { if ($filetype eq 'sty') { $filecontents=&createnewsty(); @@ -1267,6 +1313,10 @@ ENDNOTFOUND } } else { unless ($ENV{'request.state'} eq 'published') { + if ($filecontents=~/BEGIN LON-CAPA Internal/) { + &Apache::lonxml::error(&mt('This file appears to be a rendering of a Lon-CAPA resource. If this is correct, this resource will act very oddly and incorrectly.')); + } + if ($ENV{'form.attemptclean'}) { $filecontents=&htmlclean($filecontents,1); } @@ -1288,7 +1338,11 @@ ENDNOTFOUND if ($ENV{'form.editmode'} && (!($ENV{'form.viewmode'}))) { my $displayfile=$request->uri; $displayfile=~s/^\/[^\/]*//; - $result=''. + my $bodytag=''; + if ($ENV{'environment.remote'} eq 'off') { + $bodytag=&Apache::loncommon::bodytag(); + } + $result=''.$bodytag. &Apache::lonxml::message_location().'

'. $displayfile. '

'; @@ -1323,42 +1377,61 @@ sub debug { my $request=$Apache::lonxml::request; if (!$request) { $request=Apache->request; } $request->print('
DEBUG:'.&HTML::Entities::encode($_[0],'<>&"')."
\n"); + #&Apache::lonnet::logthis($_[0]); } } +sub show_error_warn_msg { + return (($Apache::lonxml::debug eq 1) || + ($ENV{'request.state'} eq 'construct') || + ($Apache::lonhomework::browse eq 'F' + && + $ENV{'form.show_errors'} eq 'on')); +} + sub error { - $errorcount++; - my $request=$Apache::lonxml::request; - if (!$request) { $request=Apache->request; } - if (($Apache::lonxml::debug eq 1) || ($ENV{'request.state'} eq 'construct') ) { - # If printing in construction space, put the error inside

-      push(@Apache::lonxml::error_messages,
-	   $Apache::lonxml::warnings_error_header.
-	   "ERROR:".join("
\n",@_)."
\n"); - $Apache::lonxml::warnings_error_header=''; - } else { - push(@Apache::lonxml::error_messages, - "An Error occured while processing this resource. The instructor has been notified.
"); - #notify author - &Apache::lonmsg::author_res_msg($ENV{'request.filename'},join('
',@_)); - #notify course - if ( $ENV{'request.course.id'} ) { - my (undef,%users)=&Apache::lonfeedback::decide_receiver(undef,0,1,1,1); - my $declutter=&Apache::lonnet::declutter($ENV{'request.filename'}); - foreach (keys %users) { - my ($user,$domain) = split(/:/, $_); - &Apache::lonmsg::user_normal_msg($user,$domain, - "Error [$declutter]",join('
',@_)); - } + $errorcount++; + if ( &show_error_warn_msg() ) { + # If printing in construction space, put the error inside

+	push(@Apache::lonxml::error_messages,
+	     $Apache::lonxml::warnings_error_header.
+	     "ERROR:".join("
\n",@_)."
\n"); + $Apache::lonxml::warnings_error_header=''; + } else { + my $errormsg; + my ($symb)=&Apache::lonnet::symbread(); + if ( !$symb ) { + #public or browsers + $errormsg=&mt("An error occured while processing this resource. The author has been notified."); + } + #notify author + &Apache::lonmsg::author_res_msg($ENV{'request.filename'},join('
',@_)); + #notify course + if ( $symb && $ENV{'request.course.id'} ) { + my (undef,%users)=&Apache::lonfeedback::decide_receiver(undef,0,1,1,1); + my $declutter=&Apache::lonnet::declutter($ENV{'request.filename'}); + my @userlist; + foreach (keys %users) { + my ($user,$domain) = split(/:/, $_); + push(@userlist,"$user\@$domain"); + &Apache::lonmsg::user_normal_msg($user,$domain, + "Error [$declutter]",join('
',@_)); + } + if ($ENV{'request.role.adv'}) { + $errormsg=&mt("An error occured while processing this resource. The course personnel ([_1]) and the author have been notified.",join(', ',@userlist)); + } else { + $errormsg=&mt("An error occured while processing this resource. The instructor has been notified."); + } + } + push(@Apache::lonxml::error_messages,"$errormsg
"); } - } } sub warning { $warningcount++; if ($ENV{'form.grade_target'} ne 'tex') { - if ($ENV{'request.state'} eq 'construct' || $Apache::lonxml::debug) { + if ( &show_error_warn_msg() ) { my $request=$Apache::lonxml::request; if (!$request) { $request=Apache->request; } push(@Apache::lonxml::warning_messages, @@ -1435,7 +1508,7 @@ sub get_param_var { } elsif ( $args !~ /my \$\Q$param\E=\"/ ) { return undef; } my $value=&Apache::run::run("{$args;".'return $'.$param.'}',$safeeval); #' &Apache::lonxml::debug("first run is $value"); - if ($value =~ /^[\$\@\%]\w+$/) { + if ($value =~ /^[\$\@\%][a-zA-Z_]\w*$/) { &Apache::lonxml::debug("doing second"); my @result=&Apache::run::run("return $value",$safeeval,1); if (!defined($result[0])) { @@ -1525,6 +1598,12 @@ sub whichuser { if (defined($ENV{'form.grade_symb'})) { my $tmp_courseid=$ENV{'form.grade_courseid'}; my $allowed=&Apache::lonnet::allowed('vgr',$tmp_courseid); + if (!$allowed && + exists($ENV{'request.course.sec'}) && + $ENV{'request.course.sec'} !~ /^\s*$/) { + $allowed=&Apache::lonnet::allowed('vgr',$ENV{'form.grade_courseid'}. + '/'.$ENV{'request.course.sec'}); + } if ($allowed) { $symb=$ENV{'form.grade_symb'}; $courseid=$ENV{'form.grade_courseid'};