--- loncom/xml/lonxml.pm	2004/10/05 18:51:50	1.339
+++ loncom/xml/lonxml.pm	2005/02/26 05:37:23	1.357
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # XML Parser Module 
 #
-# $Id: lonxml.pm,v 1.339 2004/10/05 18:51:50 albertel Exp $
+# $Id: lonxml.pm,v 1.357 2005/02/26 05:37:23 albertel 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 {
@@ -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" />';
@@ -367,23 +373,29 @@ sub xmlparse {
 
 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 {
@@ -824,9 +836,12 @@ sub increasedepth {
   if ($Apache::lonxml::depthcounter[$Apache::lonxml::depth]==1) {
     $Apache::lonxml::olddepth=$Apache::lonxml::depth;
   }
-  push(@timers,[&gettimeofday()]);
-  my $time=&tv_interval($lasttime);
-  $lasttime=[&gettimeofday()];
+  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$spacing$Apache::lonxml::depth : $Apache::lonxml::olddepth : $curdepth : $token->[1] : $time : \n");
@@ -844,9 +859,12 @@ sub decreasedepth {
     &Apache::lonxml::warning(&mt("Missing tags, unable to properly run file."));
     $Apache::lonxml::depth='-1';
   }
-  my $timer=pop(@timers);
-  my $time=&tv_interval($lasttime);
-  $lasttime=[&gettimeofday()];
+  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$spacing$Apache::lonxml::depth : $Apache::lonxml::olddepth : $curdepth : $token->[1] : $time : ".&tv_interval($timer)."\n");
@@ -1022,6 +1040,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\";";
     }
@@ -1148,7 +1168,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
 
@@ -1161,6 +1184,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();
       }
@@ -1240,6 +1272,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;
@@ -1281,7 +1315,7 @@ $bodytag
 </body>
 </html>
 ENDNOTFOUND
-    $filecontents='';
+        $filecontents='';
 	if ($ENV{'request.state'} ne 'published') {
 	    if ($filetype eq 'sty') {
 		$filecontents=&createnewsty();
@@ -1292,6 +1326,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);
 	    }
@@ -1313,7 +1351,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>';
@@ -1348,13 +1390,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.
@@ -1394,7 +1448,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,
@@ -1471,7 +1525,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])) {
@@ -1559,29 +1613,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);
 }