--- loncom/xml/lonxml.pm	2001/05/15 20:50:03	1.76
+++ loncom/xml/lonxml.pm	2001/06/02 03:59:59	1.84
@@ -7,6 +7,8 @@
 # 2/21,3/13 Guy
 # 3/29,5/4 Gerd Kortemeyer
 # 5/10 Scott Harrison
+# 5/26 Gerd Kortemeyer
+# 5/27 H. K. Ng
 
 package Apache::lonxml; 
 use vars 
@@ -15,6 +17,7 @@ use strict;
 use HTML::TokeParser;
 use Safe;
 use Safe::Hole;
+use Math::Cephes qw(:trigs :hypers :bessels erf erfc);
 use Opcode;
 
 sub register {
@@ -34,6 +37,9 @@ use Apache::run;
 use Apache::londefdef;
 use Apache::scripttag;
 use Apache::edit;
+use Apache::lonnet;
+use Apache::File;
+
 #==================================================   Main subroutine: xmlparse  
 #debugging control, to turn on debugging modify the correct handler
 $Apache::lonxml::debug=0;
@@ -166,15 +172,7 @@ sub xmlparse {
 
  my $safeeval = new Safe;
  my $safehole = new Safe::Hole;
- $safeeval->permit("entereval");
- $safeeval->permit(":base_math");
- $safeeval->deny(":base_io");
- $safehole->wrap(\&Apache::lonnet::EXT,$safeeval,'&EXT');
-#need to inspect this class of ops
-# $safeeval->deny(":base_orig");
- $safeinit .= ';$external::target='.$target.';';
- $safeinit .= ';$external::randomseed='.&Apache::lonnet::rndseed().';';
- &Apache::run::run($safeinit,$safeeval);
+ &init_safespace($target,$safeeval,$safehole,$safeinit);
 #-------------------- Redefinition of the target in the case of compound target
 
  ($target, my @tenta) = split('&&',$target);
@@ -205,8 +203,8 @@ sub xmlparse {
 				    $safeeval,\%style_for_target,@parstack);
 	 }
        } else {
-	 $result = &callsub("start_$token->[1]", $target, $token,\@parstack,
-			    \@pars, $safeeval, \%style_for_target);
+	 $result = &callsub("start_$token->[1]", $target, $token, \@stack,
+			    \@parstack, \@pars, $safeeval, \%style_for_target);
        }              
      } elsif ($token->[0] eq 'E')  {
        #clear out any tags that didn't end
@@ -227,8 +225,8 @@ sub xmlparse {
 	 }
 
        } else {
-	 $result = &callsub("end_$token->[1]", $target, $token, \@parstack,
-			    \@pars,$safeeval, \%style_for_target);
+	 $result = &callsub("end_$token->[1]", $target, $token, \@stack, 
+			    \@parstack, \@pars,$safeeval, \%style_for_target);
        }
      } else {
        &Apache::lonxml::error("Unknown token event :$token->[0]:$token->[1]:");
@@ -289,9 +287,9 @@ sub recurse {
 	push (@innerstack,$tokenpat->[1]);
 	push (@innerparstack,&parstring($tokenpat));
 	&increasedepth($tokenpat);
-	$partstring = &callsub("start_$tokenpat->[1]", 
-			       $target, $tokenpat, \@innerparstack,
-			       \@pat, $safeeval, $style_for_target);
+	$partstring = &callsub("start_$tokenpat->[1]", $target, $tokenpat,
+			       \@innerstack, \@innerparstack, \@pat,
+			       $safeeval, $style_for_target);
       } elsif ($tokenpat->[0] eq 'E') {
 	#clear out any tags that didn't end
 	while ($tokenpat->[1] ne $innerstack[$#innerstack] 
@@ -299,9 +297,9 @@ sub recurse {
 	  &Apache::lonxml::warning("Unbalanced tags in resource $innerstack['-1']");
 	  pop @innerstack;pop @innerparstack;&decreasedepth($tokenpat);
 	}
-	$partstring = &callsub("end_$tokenpat->[1]",
-			       $target, $tokenpat, \@innerparstack,
-			       \@pat, $safeeval, $style_for_target);
+	$partstring = &callsub("end_$tokenpat->[1]", $target, $tokenpat,
+			       \@innerstack, \@innerparstack, \@pat,
+			       $safeeval, $style_for_target);
       } else {
 	&Apache::lonxml::error("Unknown token event :$tokenpat->[0]:$tokenpat->[1]:");
       }
@@ -334,14 +332,15 @@ sub recurse {
 }
 
 sub callsub {
-  my ($sub,$target,$token,$parstack,$parser,$safeeval,$style)=@_;
+  my ($sub,$target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
   my $currentstring='';
   my $nodefault;
   {
     my $sub1;
     no strict 'refs';
     if ($target eq 'edit' && $token->[0] eq 'S') {
-      $currentstring = &Apache::edit::tag_start($target,$token,$parstack,$parser,
+      $currentstring = &Apache::edit::tag_start($target,$token,$tagstack,
+						$parstack,$parser,
 						$safeeval,$style);
     }
     my $tag=$token->[1];
@@ -355,8 +354,9 @@ sub callsub {
       #&Apache::lonxml::debug("Calling sub $sub in $space $metamode<br />\n");
       $sub1="$space\:\:$sub";
       $Apache::lonxml::curdepth=join('_',@Apache::lonxml::depthcounter);
-      ($currentstring,$nodefault) = &$sub1($target,$token,$parstack,$parser,
-					   $safeeval,$style);
+      ($currentstring,$nodefault) = &$sub1($target,$token,$tagstack,
+					   $parstack,$parser,$safeeval,
+					   $style);
     } else {
       #&Apache::lonxml::debug("NOT Calling sub $sub in $space $metamode<br />\n");
       if ($metamode <1) {
@@ -367,7 +367,7 @@ sub callsub {
 	}
       }
     }
-    &Apache::lonxml::debug("nodefalt:$nodefault:");
+#    &Apache::lonxml::debug("nodefalt:$nodefault:");
     if ($currentstring eq '' && $nodefault eq '') {
       if ($target eq 'edit') {
 	&Apache::lonxml::debug("doing default edit for $token->[1]");
@@ -390,6 +390,41 @@ sub callsub {
   return $currentstring;
 }
 
+sub init_safespace {
+  my ($target,$safeeval,$safehole,$safeinit) = @_;
+  $safeeval->permit("entereval");
+  $safeeval->permit(":base_math");
+  $safeeval->permit("sort");
+  $safeeval->deny(":base_io");
+  $safehole->wrap(\&Apache::lonnet::EXT,$safeeval,'&EXT');
+  
+  $safehole->wrap(\&Math::Cephes::asin,$safeeval,'&asin');
+  $safehole->wrap(\&Math::Cephes::acos,$safeeval,'&acos');
+  $safehole->wrap(\&Math::Cephes::atan,$safeeval,'&atan');
+  $safehole->wrap(\&Math::Cephes::sinh,$safeeval,'&sinh');
+  $safehole->wrap(\&Math::Cephes::cosh,$safeeval,'&cosh');
+  $safehole->wrap(\&Math::Cephes::tanh,$safeeval,'&tanh');
+  $safehole->wrap(\&Math::Cephes::asinh,$safeeval,'&asinh');
+  $safehole->wrap(\&Math::Cephes::acosh,$safeeval,'&acosh');
+  $safehole->wrap(\&Math::Cephes::atanh,$safeeval,'&atanh');
+  $safehole->wrap(\&Math::Cephes::erf,$safeeval,'&erf');
+  $safehole->wrap(\&Math::Cephes::erfc,$safeeval,'&erfc');
+  $safehole->wrap(\&Math::Cephes::j0,$safeeval,'&j0');
+  $safehole->wrap(\&Math::Cephes::j1,$safeeval,'&j1');
+  $safehole->wrap(\&Math::Cephes::jn,$safeeval,'&jn');
+  $safehole->wrap(\&Math::Cephes::jv,$safeeval,'&jv');
+  $safehole->wrap(\&Math::Cephes::y0,$safeeval,'&y0');
+  $safehole->wrap(\&Math::Cephes::y1,$safeeval,'&y1');
+  $safehole->wrap(\&Math::Cephes::yn,$safeeval,'&yn');
+  $safehole->wrap(\&Math::Cephes::yv,$safeeval,'&yv');
+  
+#need to inspect this class of ops
+# $safeeval->deny(":base_orig");
+  $safeinit .= ';$external::target='.$target.';';
+  $safeinit .= ';$external::randomseed='.&Apache::lonnet::rndseed().';';
+  &Apache::run::run($safeinit,$safeeval);
+}
+
 sub startredirection {
   $Apache::lonxml::redirection++;
   push (@Apache::lonxml::outputstack, '');
@@ -569,6 +604,47 @@ ENDSCRIPT
     return $result;
 }
 
+sub storefile {
+    my ($file,$contents)=@_;
+    if (my $fh=Apache::File->new('>'.$file)) {
+	print $fh $contents;
+        $fh->close();
+    }
+}
+
+sub inserteditinfo {
+      my ($result,$filecontents)=@_;
+      unless ($filecontents) {
+	  $filecontents=(<<SIMPLECONTENT);
+<html>
+<head>
+<title>
+                           Title of Document Goes Here
+</title>
+</head>
+<body bgcolor="#FFFFFF">
+
+                           Body of Document Goes Here
+
+</body>
+</html>
+SIMPLECONTENT
+      }
+      my $editheader='<a href="#editsection">Edit below</a><hr />';
+      my $editfooter=(<<ENDFOOTER);
+<hr />
+<a name="editsection" />
+<form method="post">
+<textarea cols="80" rows="40" name="filecont">$filecontents</textarea>
+<br />
+<input type="submit" name="savethisfile" value="Save this file" />
+</form>
+ENDFOOTER
+      $result=~s/(\<body[^\>]*\>)/$1$editheader/is;
+      $result=~s/(\<\/body\>)/$editfooter/is;
+      return $result;
+}
+
 sub handler {
   my $request=shift;
 
@@ -582,30 +658,46 @@ sub handler {
     $request->content_type('text/html');
   }
   
-#  $request->print(<<ENDHEADER);
-#<html>
-#<head>
-#<title>Just test</title>
-#</head>
-#<body bgcolor="#FFFFFF">
-#ENDHEADER
-#  &Apache::lonhomework::send_header($request);
   $request->send_http_header;
   
   return OK if $request->header_only;
 
 
   my $file=&Apache::lonnet::filelocation("",$request->uri);
+#
+# Edit action? Save file.
+#
+  unless ($ENV{'request.state'} eq 'published') {
+      if ($ENV{'form.savethisfile'}) {
+	  &storefile($file,$ENV{'form.filecont'});
+      }
+  }
   my %mystyle;
   my $result = ''; 
   my $filecontents=&Apache::lonnet::getfile($file);
   if ($filecontents == -1) {
-    &Apache::lonxml::error("<b> Unable to find <i>$file</i></b>");
+    $result=(<<ENDNOTFOUND);
+<html>
+<head>
+<title>File not found</title>
+</head>
+<body bgcolor="#FFFFFF">
+<b>File not found: $file</b>
+</body>
+</html>
+ENDNOTFOUND
     $filecontents='';
   } else {
     $result = &Apache::lonxml::xmlparse($target,$filecontents,'',%mystyle);
   }
 
+#
+# Edit action? Insert editing commands
+#
+  unless ($ENV{'request.state'} eq 'published') {
+      $result=&inserteditinfo($result,$filecontents);
+  }
+
   $request->print($result);
 
   writeallows($request->uri);
@@ -646,6 +738,14 @@ sub warning {
   }
 }
 
+sub get_param {
+  my ($param,$parstack,$safeeval,$context) = @_;
+  if ( ! $context ) { $context = -1; }
+  my $args ='';
+  if ( $#$parstack > (-2-$context) ) { $args=$$parstack[$context]; }
+  return &Apache::run::run("{$args;".'return $'.$param.'}',$safeeval); #'
+}
+
 sub register_insert {
   my @data = split /\n/, &Apache::lonnet::getfile('/home/httpd/lonTabs/insertlist.tab');
   my $i;