--- loncom/xml/lonxml.pm 2004/08/29 08:17:22 1.332.2.1 +++ loncom/xml/lonxml.pm 2004/11/30 22:57:16 1.348 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # XML Parser Module # -# $Id: lonxml.pm,v 1.332.2.1 2004/08/29 08:17:22 albertel Exp $ +# $Id: lonxml.pm,v 1.348 2004/11/30 22:57:16 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -51,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) = @_; @@ -159,19 +159,28 @@ sub xmlbegin { .'<html xmlns:math="http://www.w3.org/1998/Math/MathML" ' .'xmlns="http://www.w3.org/TR/REC-html40">'; } else { - $output='<html>'; + $output='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html>'; } 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).'</html>'; + my $discussion=&Apache::lonfeedback::list_discussion($mode,$status); + if ($target eq 'tex') { + $discussion.='<tex>\keephidden{ENDOFPROBLEM}\vskip 0.5mm\noindent\makebox[\textwidth/$number_of_columns][b]{\hrulefill}\end{document}</tex>'; + &Apache::lonxml::newparser($parser,\$discussion,''); + return ''; + } else { + return $discussion.'</html>'; + } } sub tokeninputfield { @@ -279,7 +288,7 @@ sub fontsettings() { my $headerstring=''; if (($ENV{'browser.os'} eq 'mac') && (!$ENV{'browser.mathml'})) { $headerstring.= - '<meta Content-Type="text/html; charset=x-mac-roman">'; + '<meta Content-Type="text/html; charset=x-mac-roman" />'; } elsif (!$ENV{'browser.mathml'} && $ENV{'browser.unicode'}) { $headerstring.= '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />'; @@ -312,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); @@ -805,6 +816,8 @@ sub initdepth { $Apache::lonxml::olddepth=-1; } +my @timers; +my $lasttime; sub increasedepth { my ($token) = @_; $Apache::lonxml::depth++; @@ -812,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 "<br />s $Apache::lonxml::depth : $Apache::lonxml::olddepth : $curdepth : $token->[1]\n"; } @@ -828,8 +848,15 @@ 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 "<br />e $Apache::lonxml::depth : $Apache::lonxml::olddepth : $token->[1] : $curdepth\n"; } @@ -1002,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\";"; } @@ -1127,7 +1156,11 @@ sub inserteditinfo { my $initialize=''; if ($filetype eq 'html') { my $addbuttons=&Apache::lonhtmlcommon::htmlareaaddbuttons(); - $initialize=&Apache::lonhtmlcommon::htmlareaheaders().(<<FULLPAGE); + $initialize=&Apache::lonhtmlcommon::htmlareaheaders(). + &Apache::lonhtmlcommon::spellheader(); + if (!&Apache::lonhtmlcommon::htmlareablocked() && + &Apache::lonhtmlcommon::htmlareabrowser()) { + $initialize.=(<<FULLPAGE); <script type="text/javascript"> $addbuttons @@ -1140,6 +1173,15 @@ $addbuttons } </script> FULLPAGE + } else { + $initialize.=(<<FULLPAGE); +<script type="text/javascript"> +$addbuttons + function initDocument() { + } +</script> +FULLPAGE + } $result=~s/\<body([^\>]*)\>/\<body onload="initDocument()" $1\>/i; $xml_help=&Apache::loncommon::helpLatexCheatsheet(); } @@ -1157,12 +1199,13 @@ $cleanbut <input type="submit" name="savethisfile" accesskey="s" value="$lt{'st'}" /> <input type="submit" name="viewmode" accesskey="v" value="$lt{'vi'}" /> BUTTONS + $buttons.=&Apache::lonhtmlcommon::spelllink('xmledit','filecont'); $buttons.=&Apache::lonhtmlcommon::htmlareaselectactive('filecont'); my $editfooter=(<<ENDFOOTER); $initialize <hr /> <a name="editsection" /> -<form method="post"> +<form method="post" name="xmledit"> $xml_help <input type="hidden" name="editmode" value="$lt{'ed'}" /> $buttons<br /> @@ -1259,7 +1302,7 @@ $bodytag </body> </html> ENDNOTFOUND - $filecontents=''; + $filecontents=''; if ($ENV{'request.state'} ne 'published') { if ($filetype eq 'sty') { $filecontents=&createnewsty(); @@ -1270,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); } @@ -1326,43 +1373,61 @@ sub debug { my $request=$Apache::lonxml::request; if (!$request) { $request=Apache->request; } $request->print('<font size="-2"><pre>DEBUG:'.&HTML::Entities::encode($_[0],'<>&"')."</pre></font>\n"); -# &Apache::lonnet::logthis($_[0]); + #&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 <pre></pre> - push(@Apache::lonxml::error_messages, - $Apache::lonxml::warnings_error_header. - "<b>ERROR:</b>".join("<br />\n",@_)."<br />\n"); - $Apache::lonxml::warnings_error_header=''; - } else { - push(@Apache::lonxml::error_messages, - "<b>An Error occured while processing this resource. The instructor has been notified.</b> <br />"); - #notify author - &Apache::lonmsg::author_res_msg($ENV{'request.filename'},join('<br />',@_)); - #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('<br />',@_)); - } + $errorcount++; + if ( &show_error_warn_msg() ) { + # If printing in construction space, put the error inside <pre></pre> + push(@Apache::lonxml::error_messages, + $Apache::lonxml::warnings_error_header. + "<b>ERROR:</b>".join("<br />\n",@_)."<br />\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('<br />',@_)); + #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('<br />',@_)); + } + 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,"<b>$errormsg</b> <br />"); } - } } 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, @@ -1439,7 +1504,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])) { @@ -1529,6 +1594,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'};