--- loncom/xml/lonxml.pm 2004/10/05 18:54:49 1.340 +++ loncom/xml/lonxml.pm 2005/03/10 02:34:59 1.361 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # XML Parser Module # -# $Id: lonxml.pm,v 1.340 2004/10/05 18:54:49 albertel Exp $ +# $Id: lonxml.pm,v 1.361 2005/03/10 02:34:59 www Exp $ # # Copyright Michigan State University Board of Trustees # @@ -149,19 +149,25 @@ $Apache::lonxml::post_evaluate=1; $Apache::lonxml::warnings_error_header=''; sub xmlbegin { - my $output=''; - @htmlareafields=(); - if ($ENV{'browser.mathml'}) { - $output='<?xml version="1.0"?>' - .'<?xml-stylesheet type="text/css" href="/adm/MathML/mathml.css"?>' - .'<!DOCTYPE html SYSTEM "/adm/MathML/mathml.dtd" ' - .'[<!ENTITY mathns "http://www.w3.org/1998/Math/MathML">]>' + my ($style)=@_; + my $output=''; + @htmlareafields=(); + if ($ENV{'browser.mathml'}) { + $output='<?xml version="1.0"?>' + #.'<?xml-stylesheet type="text/css" href="/adm/MathML/mathml.css"?>'."\n" +# .'<!DOCTYPE html SYSTEM "/adm/MathML/mathml.dtd" ' + +# .'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" [<!ENTITY mathns "http://www.w3.org/1998/Math/MathML">] >' + .'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN" "http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd">' .'<html xmlns:math="http://www.w3.org/1998/Math/MathML" ' - .'xmlns="http://www.w3.org/TR/REC-html40">'; - } else { - $output='<html>'; - } - return $output; + .'xmlns="http://www.w3.org/1999/xhtml">'; + } else { + $output='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html>'; + } + if ($style eq 'encode') { + $output=&HTML::Entities::encode($output,'<>&"'); + } + return $output; } sub xmlend { @@ -178,7 +184,7 @@ sub xmlend { &Apache::lonxml::newparser($parser,\$discussion,''); return ''; } else { - return $discussion.'</html>'; + return $discussion.&Apache::loncommon::endbodytag(); } } @@ -283,11 +289,11 @@ sub printtokenheader { } } -sub fontsettings() { +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" />'; @@ -352,8 +358,8 @@ sub xmlparse { my @stack = (); my @parstack = (); - &initdepth; - + &initdepth(); + &init_alarm(); my $finaloutput = &inner_xmlparse($target,\@stack,\@parstack,\@pars, $safeeval,\%style_for_target); @@ -362,28 +368,37 @@ sub xmlparse { } &do_registered_ssi(); if ($Apache::lonxml::counter_changed) { &store_counter() } + if ($ENV{'form.return_only_error_and_warning_counts'}) { + return "$errorcount:$warningcount"; + } return $finaloutput; } sub htmlclean { my ($raw,$full)=@_; +# Take care of CRLF etc - my $tree = HTML::TreeBuilder->new; - $tree->ignore_unknown(0); - - $tree->parse($raw); - - my $output= $tree->as_HTML(undef,' '); - - $output=~s/\<(br|hr|img|meta|allow)(.*?)\>/\<$1$2 \/\>/gis; - $output=~s/\<\/(br|hr|img|meta|allow)\>//gis; + $raw=~s/\r\f/\n/gs; $raw=~s/\f\r/\n/gs; + $raw=~s/\r\n/\n/gs; $raw=~s/\n\r/\n/gs; + $raw=~s/\f/\n/gs; $raw=~s/\r/\n/gs; + $raw=~s/\&\#10\;/\n/gs; $raw=~s/\&\#13\;/\n/gs; + +# Generate empty tags, remove wrong end tags + $raw=~s/\<(br|hr|img|meta|allow|basefont)([^\>\/]*?)\>/\<$1$2 \/\>/gis; + $raw=~s/\<\/(br|hr|img|meta|allow|basefont)\>//gis; unless ($full) { - $output=~s/\<[\/]*(body|head|html)\>//gis; + $raw=~s/\<[\/]*(body|head|html)\>//gis; } - - $tree = $tree->delete; - - return $output; +# Make standard tags lowercase + foreach ('html','body','head','meta','h1','h2','h3','h4','b','i','m', + 'table','tr','td','th','p','br','hr','img','embed','font', + 'a','strong','center','title','basefont','li','ol','ul', + 'input','select','form','option','script','pre') { + $raw=~s/\<$_\s*\>/\<$_\>/gis; + $raw=~s/\<\/$_\s*\>/<\/$_\>/gis; + $raw=~s/\<$_\s([^\>]*)\>/<$_ $1\>/gis; + } + return $raw; } sub latex_special_symbols { @@ -780,6 +795,28 @@ sub default_homework_load { } } +{ + my $alarm_depth; + sub init_alarm { + alarm(0); + $alarm_depth=0; + } + + sub start_alarm { + if ($alarm_depth<1) { + my $old=alarm($Apache::lonnet::perlvar{'lonScriptTimeout'}); + if ($old) { + &Apache::lonxml::error("Cancelled an alarm of $old, this shouldn't occur."); + } + } + $alarm_depth++; + } + + sub end_alarm { + $alarm_depth--; + if ($alarm_depth<1) { alarm(0); } + } +} my $metamode_was; sub startredirection { if (!$Apache::lonxml::redirection) { @@ -1028,6 +1065,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\";"; } @@ -1154,7 +1193,10 @@ sub inserteditinfo { if ($filetype eq 'html') { my $addbuttons=&Apache::lonhtmlcommon::htmlareaaddbuttons(); $initialize=&Apache::lonhtmlcommon::htmlareaheaders(). - &Apache::lonhtmlcommon::spellheader().(<<FULLPAGE); + &Apache::lonhtmlcommon::spellheader(); + if (!&Apache::lonhtmlcommon::htmlareablocked() && + &Apache::lonhtmlcommon::htmlareabrowser()) { + $initialize.=(<<FULLPAGE); <script type="text/javascript"> $addbuttons @@ -1167,6 +1209,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(); } @@ -1246,6 +1297,8 @@ sub handler { &Apache::loncommon::content_type($request,'text/html'); } &Apache::loncommon::no_cache($request); + $request->set_last_modified(&Apache::lonnet::metadata($request->uri, + 'lastrevisiondate')); $request->send_http_header; return OK if $request->header_only; @@ -1287,7 +1340,7 @@ $bodytag </body> </html> ENDNOTFOUND - $filecontents=''; + $filecontents=''; if ($ENV{'request.state'} ne 'published') { if ($filetype eq 'sty') { $filecontents=&createnewsty(); @@ -1298,6 +1351,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); } @@ -1319,7 +1376,11 @@ ENDNOTFOUND if ($ENV{'form.editmode'} && (!($ENV{'form.viewmode'}))) { my $displayfile=$request->uri; $displayfile=~s/^\/[^\/]*//; - $result='<html><body bgcolor="#FFFFFF">'. + my $bodytag='<body bgcolor="#FFFFFF">'; + if ($ENV{'environment.remote'} eq 'off') { + $bodytag=&Apache::loncommon::bodytag(); + } + $result='<html>'.$bodytag. &Apache::lonxml::message_location().'<h3>'. $displayfile. '</h3></body></html>'; @@ -1354,13 +1415,25 @@ 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 { + if ($ENV{'request.filename'} eq '/home/httpd/html/res/lib/templates/simpleproblem.problem' && + &Apache::lonnet::allowed('mdc',$ENV{'request.course.id'})) { + return 1; + } + 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++; - if (($Apache::lonxml::debug eq 1) || ($ENV{'request.state'} eq 'construct') ) { + 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. @@ -1400,7 +1473,7 @@ 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, @@ -1477,7 +1550,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])) { @@ -1565,29 +1638,36 @@ sub whichuser { my ($passedsymb)=@_; my ($symb,$courseid,$domain,$name,$publicuser); if (defined($ENV{'form.grade_symb'})) { - my $tmp_courseid=$ENV{'form.grade_courseid'}; - my $allowed=&Apache::lonnet::allowed('vgr',$tmp_courseid); - if ($allowed) { - $symb=$ENV{'form.grade_symb'}; - $courseid=$ENV{'form.grade_courseid'}; - $domain=$ENV{'form.grade_domain'}; - $name=$ENV{'form.grade_username'}; - } - } else { - if (!$passedsymb) { - $symb=&Apache::lonnet::symbread(); - } else { - $symb=$passedsymb; + my ($tmp_courseid)= + &Apache::loncommon::get_env_multiple('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',$tmp_courseid. + '/'.$ENV{'request.course.sec'}); } - $courseid=$ENV{'request.course.id'}; - $domain=$ENV{'user.domain'}; - $name=$ENV{'user.name'}; - if ($name eq 'public' && $domain eq 'public') { - if (!defined($ENV{'form.username'})) { - $ENV{'form.username'}.=time.rand(10000000); - } - $name.=$ENV{'form.username'}; + if ($allowed) { + ($symb)=&Apache::loncommon::get_env_multiple('form.grade_symb'); + $courseid=$tmp_courseid; + ($domain)=&Apache::loncommon::get_env_multiple('form.grade_domain'); + ($name)=&Apache::loncommon::get_env_multiple('form.grade_username'); + return ($symb,$courseid,$domain,$name,$publicuser); + } + } + if (!$passedsymb) { + $symb=&Apache::lonnet::symbread(); + } else { + $symb=$passedsymb; + } + $courseid=$ENV{'request.course.id'}; + $domain=$ENV{'user.domain'}; + $name=$ENV{'user.name'}; + if ($name eq 'public' && $domain eq 'public') { + if (!defined($ENV{'form.username'})) { + $ENV{'form.username'}.=time.rand(10000000); } + $name.=$ENV{'form.username'}; } return ($symb,$courseid,$domain,$name,$publicuser); }