Diff for /loncom/xml/lonxml.pm between versions 1.333 and 1.531.2.20

version 1.333, 2004/07/27 23:35:34 version 1.531.2.20, 2016/08/05 20:57:58
Line 37 Line 37
 # to any other parties under any circumstances.  # to any other parties under any circumstances.
 #  #
   
   =pod
   
   =head1 NAME
   
   Apache::lonxml
   
   =head1 SYNOPSIS
   
   XML Parsing Module
   
   This is part of the LearningOnline Network with CAPA project
   described at http://www.lon-capa.org.
   
   
   =head1 SUBROUTINES
   
   =cut
   
   
   
 package Apache::lonxml;   package Apache::lonxml; 
 use vars   use vars 
 qw(@pwd @outputstack $redirection $import @extlinks $metamode $evaluate %insertlist @namespace $errorcount $warningcount @htmlareafields);  qw(@pwd @outputstack $redirection $import @extlinks $metamode $evaluate %insertlist @namespace $errorcount $warningcount);
 use strict;  use strict;
   use LONCAPA;
 use HTML::LCParser();  use HTML::LCParser();
 use HTML::TreeBuilder();  use HTML::TreeBuilder();
 use HTML::Entities();  use HTML::Entities();
Line 51  use Math::Cephes(); Line 71  use Math::Cephes();
 use Math::Random();  use Math::Random();
 use Opcode();  use Opcode();
 use POSIX qw(strftime);  use POSIX qw(strftime);
   use Time::HiRes qw( gettimeofday tv_interval );
   use Symbol();
   
 sub register {  sub register {
   my ($space,@taglist) = @_;    my ($space,@taglist) = @_;
Line 81  use Apache::languagetags(); Line 102  use Apache::languagetags();
 use Apache::edit();  use Apache::edit();
 use Apache::inputtags();  use Apache::inputtags();
 use Apache::outputtags();  use Apache::outputtags();
 use Apache::lonnet();  use Apache::lonnet;
 use Apache::File();  use Apache::File();
 use Apache::loncommon();  use Apache::loncommon();
 use Apache::lonfeedback();  use Apache::lonfeedback();
 use Apache::lonmsg();  use Apache::lonmsg();
 use Apache::loncacc();  use Apache::loncacc();
   use Apache::lonmaxima();
   use Apache::lonr();
 use Apache::lonlocal;  use Apache::lonlocal;
   use Apache::lonhtmlcommon();
   use Apache::functionplotresponse();
   use Apache::lonnavmaps();
   
   #====================================   Main subroutine: xmlparse  
   
 #==================================================   Main subroutine: xmlparse    
 #debugging control, to turn on debugging modify the correct handler  #debugging control, to turn on debugging modify the correct handler
   
 $Apache::lonxml::debug=0;  $Apache::lonxml::debug=0;
   
 # keeps count of the number of warnings and errors generated in a parse  # keeps count of the number of warnings and errors generated in a parse
Line 116  $metamode = 0; Line 144  $metamode = 0;
 # turns on and of run::evaluate actually derefencing var refs  # turns on and of run::evaluate actually derefencing var refs
 $evaluate = 1;  $evaluate = 1;
   
 # data structure for eidt mode, determines what tags can go into what other tags  # data structure for edit mode, determines what tags can go into what other tags
 %insertlist=();  %insertlist=();
   
 # stores the list of active tag namespaces  # stores the list of active tag namespaces
 @namespace=();  @namespace=();
   
 # has the dynamic menu been updated to know about this resource  # stores all Scrit Vars displays for later showing
 $Apache::lonxml::registered=0;  my @script_var_displays=();
   
 # a pointer the the Apache request object  # a pointer the the Apache request object
 $Apache::lonxml::request='';  $Apache::lonxml::request='';
Line 132  $Apache::lonxml::request=''; Line 160  $Apache::lonxml::request='';
 $Apache::lonxml::counter=1;  $Apache::lonxml::counter=1;
 $Apache::lonxml::counter_changed=0;  $Apache::lonxml::counter_changed=0;
   
   # Part counter hash.   In analysis mode, the
   # problems can use this to record which parts increment the counter
   # by how much.  The counter subs will maintain this hash via
   # their optional part parameters.  Note that the assumption is that
   # analysis is done in one request and therefore it is not necessary to
   # save this information request-to-request.
   
   
   %Apache::lonxml::counters_per_part = ();
   
 #internal check on whether to look at style defs  #internal check on whether to look at style defs
 $Apache::lonxml::usestyle=1;  $Apache::lonxml::usestyle=1;
   
Line 148  $Apache::lonxml::post_evaluate=1; Line 186  $Apache::lonxml::post_evaluate=1;
 #a header message to emit in the case of any generated warning or errors  #a header message to emit in the case of any generated warning or errors
 $Apache::lonxml::warnings_error_header='';  $Apache::lonxml::warnings_error_header='';
   
 sub xmlbegin {  #  Control whether or not LaTeX symbols should be substituted for their
   my $output='';  #  \ style equivalents...this may be turned off e.g. in an verbatim
   @htmlareafields=();  #  environment.
   if ($ENV{'browser.mathml'}) {  
       $output='<?xml version="1.0"?>'  $Apache::lonxml::substitute_LaTeX_symbols = 1; # Starts out on.
             .'<?xml-stylesheet type="text/css" href="/adm/MathML/mathml.css"?>'  
             .'<!DOCTYPE html SYSTEM "/adm/MathML/mathml.dtd" '  sub enable_LaTeX_substitutions {
             .'[<!ENTITY mathns "http://www.w3.org/1998/Math/MathML">]>'      $Apache::lonxml::substitute_LaTeX_symbols = 1;
             .'<html xmlns:math="http://www.w3.org/1998/Math/MathML" '   }
  .'xmlns="http://www.w3.org/TR/REC-html40">';  sub disable_LaTeX_substitutions {
   } else {      $Apache::lonxml::substitute_LaTeX_symbols = 0;
       $output='<html>';  
   }  
   return $output;  
 }  }
   
 sub xmlend {  sub xmlend {
       my ($target,$parser)=@_;
     my $mode='xml';      my $mode='xml';
     my $status='OPEN';      my $status='OPEN';
     if ($Apache::lonhomework::parsing_a_problem) {      if ($Apache::lonhomework::parsing_a_problem ||
    $Apache::lonhomework::parsing_a_task ) {
  $mode='problem';   $mode='problem';
  $status=$Apache::inputtags::status[-1];    $status=$Apache::inputtags::status[-1]; 
     }      }
     return &Apache::lonfeedback::list_discussion($mode,$status).'</html>';      my $discussion;
       &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
      ['LONCAPA_INTERNAL_no_discussion']);
       if (
              (   (!exists($env{'form.LONCAPA_INTERNAL_no_discussion'})) 
               || ($env{'form.LONCAPA_INTERNAL_no_discussion'} ne 'true')
              ) 
           && ($env{'form.inhibitmenu'} ne 'yes')
          ) {
           $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 '';
       }
   
       return $discussion;
 }  }
   
 sub tokeninputfield {  sub tokeninputfield {
Line 180  sub tokeninputfield { Line 234  sub tokeninputfield {
     return (<<ENDINPUTFIELD)      return (<<ENDINPUTFIELD)
 <script type="text/javascript">  <script type="text/javascript">
     function updatetoken() {      function updatetoken() {
  var comp=new Array;          var comp=new Array;
         var barcode=unescape(document.tokeninput.barcode.value);          var barcode=unescape(document.tokeninput.barcode.value);
         comp=barcode.split('*');          comp=barcode.split('*');
         if (typeof(comp[0])!="undefined") {          if (typeof(comp[0])!="undefined") {
     document.tokeninput.codeone.value=comp[0];              document.tokeninput.codeone.value=comp[0];
  }          }
         if (typeof(comp[1])!="undefined") {          if (typeof(comp[1])!="undefined") {
     document.tokeninput.codetwo.value=comp[1];              document.tokeninput.codetwo.value=comp[1];
  }          }
         if (typeof(comp[2])!="undefined") {          if (typeof(comp[2])!="undefined") {
             comp[2]=comp[2].toUpperCase();              comp[2]=comp[2].toUpperCase();
     document.tokeninput.codethree.value=comp[2];              document.tokeninput.codethree.value=comp[2];
  }          }
         document.tokeninput.barcode.value='';          document.tokeninput.barcode.value='';
     }        }
 </script>  </script>
 <form method="post" name="tokeninput">  <form method="post" name="tokeninput" action="">
 <table border="2" bgcolor="#FFFFBB">  <table border="2" bgcolor="#FFFFBB">
 <tr><th>DocID Checkin</th></tr>  <tr><th>DocID Checkin</th></tr>
 <tr><td>  <tr><td>
 <table>  <table>
 <tr>  <tr>
 <td>Scan in Barcode</td>  <td>Scan in Barcode</td>
 <td><input type="text" size="22" name="barcode"   <td><input type="text" size="22" name="barcode"
 onChange="updatetoken()"/></td>  onchange="updatetoken()"/></td>
 </tr>  </tr>
 <tr><td><i>or</i> Type in DocID</td>  <tr><td><i>or</i> Type in DocID</td>
 <td>  <td>
Line 212  onChange="updatetoken()"/></td> Line 266  onChange="updatetoken()"/></td>
 <b><font size="+2">*</font></b>  <b><font size="+2">*</font></b>
 <input type="text" size="5" name="codetwo" />  <input type="text" size="5" name="codetwo" />
 <b><font size="+2">*</font></b>  <b><font size="+2">*</font></b>
 <input type="text" size="10" name="codethree" value="$defhost"   <input type="text" size="10" name="codethree" value="$defhost"
 onChange="this.value=this.value.toUpperCase()" />  onchange="this.value=this.value.toUpperCase()" />
 </td></tr>  </td></tr>
 </table>  </table>
 </td></tr>  </td></tr>
Line 226  ENDINPUTFIELD Line 280  ENDINPUTFIELD
 sub maketoken {  sub maketoken {
     my ($symb,$tuname,$tudom,$tcrsid)=@_;      my ($symb,$tuname,$tudom,$tcrsid)=@_;
     unless ($symb) {      unless ($symb) {
  $symb=&Apache::lonnet::symbread();          $symb=&Apache::lonnet::symbread();
     }      }
     unless ($tuname) {      unless ($tuname) {
  $tuname=$ENV{'user.name'};          $tuname=$env{'user.name'};
         $tudom=$ENV{'user.domain'};          $tudom=$env{'user.domain'};
         $tcrsid=$ENV{'request.course.id'};          $tcrsid=$env{'request.course.id'};
     }      }
   
     return &Apache::lonnet::checkout($symb,$tuname,$tudom,$tcrsid);      return &Apache::lonnet::checkout($symb,$tuname,$tudom,$tcrsid);
 }  }
   
Line 241  sub printtokenheader { Line 294  sub printtokenheader {
     my ($target,$token,$tsymb,$tcrsid,$tudom,$tuname)=@_;      my ($target,$token,$tsymb,$tcrsid,$tudom,$tuname)=@_;
     unless ($token) { return ''; }      unless ($token) { return ''; }
   
     my ($symb,$courseid,$domain,$name) = &Apache::lonxml::whichuser();      my ($symb,$courseid,$domain,$name) = &Apache::lonnet::whichuser();
     unless ($tsymb) {      unless ($tsymb) {
  $tsymb=$symb;          $tsymb=$symb;
     }      }
     unless ($tuname) {      unless ($tuname) {
  $tuname=$name;          $tuname=$name;
         $tudom=$domain;          $tudom=$domain;
         $tcrsid=$courseid;          $tcrsid=$courseid;
     }      }
   
     my %reply=&Apache::lonnet::get('environment',      my $plainname=&Apache::loncommon::plainname($tuname,$tudom);
               ['firstname','middlename','lastname','generation'],  
               $tudom,$tuname);  
     my $plainname=$reply{'firstname'}.' '.   
                   $reply{'middlename'}.' '.  
                   $reply{'lastname'}.' '.  
   $reply{'generation'};  
   
     if ($target eq 'web') {      if ($target eq 'web') {
         my %idhash=&Apache::lonnet::idrget($tudom,($tuname));          my %idhash=&Apache::lonnet::idrget($tudom,($tuname));
  return           return
  '<img align="right" src="/cgi-bin/barcode.png?encode='.$token.'" />'.   '<img align="right" src="/cgi-bin/barcode.png?encode='.$token.'" />'.
                &mt('Checked out for').' '.$plainname.                 &mt('Checked out for').' '.$plainname.
                '<br />'.&mt('User').': '.$tuname.' at '.$tudom.                 '<br />'.&mt('User').': '.$tuname.' at '.$tudom.
        '<br />'.&mt('ID').': '.$idhash{$tuname}.                 '<br />'.&mt('ID').': '.$idhash{$tuname}.
        '<br />'.&mt('CourseID').': '.$tcrsid.                 '<br />'.&mt('CourseID').': '.$tcrsid.
        '<br />'.&mt('Course').': '.$ENV{'course.'.$tcrsid.'.description'}.                 '<br />'.&mt('Course').': '.$env{'course.'.$tcrsid.'.description'}.
                '<br />'.&mt('DocID').': '.$token.                 '<br />'.&mt('DocID').': '.$token.
                '<br />'.&mt('Time').': '.&Apache::lonlocal::locallocaltime().'<hr />';                 '<br />'.&mt('Time').': '.&Apache::lonlocal::locallocaltime().'<hr />';
     } else {      } else {
Line 275  sub printtokenheader { Line 322  sub printtokenheader {
     }      }
 }  }
   
 sub fontsettings() {  
     my $headerstring='';  
     if (($ENV{'browser.os'} eq 'mac') && (!$ENV{'browser.mathml'})) {   
  $headerstring.=  
     '<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" />';  
     }  
     return $headerstring;  
 }  
   
 sub printalltags {  sub printalltags {
   my $temp;      my $temp;
   foreach $temp (sort keys %Apache::lonxml::alltags) {      foreach $temp (sort keys %Apache::lonxml::alltags) {
     &Apache::lonxml::debug("$temp -- ".          &Apache::lonxml::debug("$temp -- ".
   join(',',@{ $Apache::lonxml::alltags{$temp} }));                                 join(',',@{ $Apache::lonxml::alltags{$temp} }));
   }      }
 }  }
   
 sub xmlparse {  sub xmlparse {
Line 300  sub xmlparse { Line 335  sub xmlparse {
   
  &setup_globals($request,$target);   &setup_globals($request,$target);
  &Apache::inputtags::initialize_inputtags();   &Apache::inputtags::initialize_inputtags();
    &Apache::bridgetask::initialize_bridgetask();
  &Apache::outputtags::initialize_outputtags();   &Apache::outputtags::initialize_outputtags();
  &Apache::edit::initialize_edit();   &Apache::edit::initialize_edit();
  &Apache::londefdef::initialize_londefdef();   &Apache::londefdef::initialize_londefdef();
Line 308  sub xmlparse { Line 344  sub xmlparse {
 # do we have a course style file?  # do we have a course style file?
 #  #
   
  if ($ENV{'request.course.id'} && $ENV{'request.state'} ne 'construct') {   if ($env{'request.course.id'} && $env{'request.state'} ne 'construct') {
      my $bodytext=       my $bodytext=
  $ENV{'course.'.$ENV{'request.course.id'}.'.default_xml_style'};   $env{'course.'.$env{'request.course.id'}.'.default_xml_style'};
      if ($bodytext) {       if ($bodytext) {
        my $location=&Apache::lonnet::filelocation('',$bodytext);   foreach my $file (split(',',$bodytext)) {
        my $styletext=&Apache::lonnet::getfile($location);       my $location=&Apache::lonnet::filelocation('',$file);
        if ($styletext ne '-1') {       my $styletext=&Apache::lonnet::getfile($location);
           %style_for_target = (%style_for_target,       if ($styletext ne '-1') {
                           &Apache::style::styleparser($target,$styletext));   %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'});       }
    } elsif ($env{'construct.style'}
     && ($env{'request.state'} eq 'construct')) {
        my $location=&Apache::lonnet::filelocation('',$env{'construct.style'});
      my $styletext=&Apache::lonnet::getfile($location);       my $styletext=&Apache::lonnet::getfile($location);
        if ($styletext ne '-1') {       if ($styletext ne '-1') {
           %style_for_target = (%style_for_target,   %style_for_target = (%style_for_target,
                           &Apache::style::styleparser($target,$styletext));        &Apache::style::styleparser($target,$styletext));
       }       }
  }   }
 #&printalltags();  #&printalltags();
  my @pars = ();   my @pars = ();
  my $pwd=$ENV{'request.filename'};   my $pwd=$env{'request.filename'};
  $pwd =~ s:/[^/]*$::;   $pwd =~ s:/[^/]*$::;
  &newparser(\@pars,\$content_file_string,$pwd);   &newparser(\@pars,\$content_file_string,$pwd);
   
Line 342  sub xmlparse { Line 381  sub xmlparse {
   
  my @stack = ();   my @stack = ();
  my @parstack = ();   my @parstack = ();
  &initdepth;   &initdepth();
    &init_alarm();
  my $finaloutput = &inner_xmlparse($target,\@stack,\@parstack,\@pars,   my $finaloutput = &inner_xmlparse($target,\@stack,\@parstack,\@pars,
    $safeeval,\%style_for_target);     $safeeval,\%style_for_target,1);
   
  if ($ENV{'request.uri'}) {   if (@stack) {
     &writeallows($ENV{'request.uri'});       &warning(&mt('At end of file some tags were still left unclosed:').
         ' <tt>&lt;'.join('&gt;</tt>, <tt>&lt;',reverse(@stack)).
         '&gt;</tt>');
    }
    if ($env{'request.uri'}) {
       &writeallows($env{'request.uri'});
  }   }
  &do_registered_ssi();   &do_registered_ssi();
  if ($Apache::lonxml::counter_changed) { &store_counter() }   if ($Apache::lonxml::counter_changed) { &store_counter() }
  return $finaloutput;  
 }  
   
 sub htmlclean {   &clean_safespace($safeeval);
     my ($raw,$full)=@_;  
   
     my $tree = HTML::TreeBuilder->new;   if (@script_var_displays) {
     $tree->ignore_unknown(0);       if ($finaloutput =~ m{</body>\s*</html>\s*$}s) {
            my $scriptoutput = join('',@script_var_displays);
     $tree->parse($raw);           $finaloutput=~s{(</body>\s*</html>)\s*$}{$scriptoutput$1}s;
        } else {
     my $output= $tree->as_HTML(undef,' ');           $finaloutput .= join('',@script_var_displays);
        }
     $output=~s/\<(br|hr|img|meta|allow)(.*?)\>/\<$1$2 \/\>/gis;       undef(@script_var_displays);
     $output=~s/\<\/(br|hr|img|meta|allow)\>//gis;   }
     unless ($full) {   &init_state();
        $output=~s/\<[\/]*(body|head|html)\>//gis;   if ($env{'form.return_only_error_and_warning_counts'}) {
     }       if ($env{'request.filename'}=~/\.(html|htm|xml)$/i) { 
           my $error=&verify_html($content_file_string);
     $tree = $tree->delete;          if ($error) { $errorcount++; }
        }
     return $output;       return "$errorcount:$warningcount";
    }
    return $finaloutput;
 }  }
   
 sub latex_special_symbols {  sub latex_special_symbols {
     my ($string,$where)=@_;      my ($string,$where)=@_;
       #
       #  If e.g. in verbatim mode, then don't substitute.
       #  but return original string.
       #
       if (!($Apache::lonxml::substitute_LaTeX_symbols)) {
    return $string;
       }
     if ($where eq 'header') {      if ($where eq 'header') {
  $string =~ s/(\\|_|\^)/ /g;   $string =~ s/\\/\$\\backslash\$/g; # \  -> $\backslash$ per LaTex line by line pg  10.
  $string =~ s/(\$|%|\{|\})/\\$1/g;   $string =~ s/(\$|%|\{|\})/\\$1/g;
  $string =~ s/_/ /g;  
  $string=&Apache::lonprintout::character_chart($string);   $string=&Apache::lonprintout::character_chart($string);
  # any & or # leftover should be safe to just escape   # any & or # leftover should be safe to just escape
         $string=~s/([^\\])\&/$1\\\&/g;          $string=~s/([^\\])\&/$1\\\&/g;
         $string=~s/([^\\])\#/$1\\\#/g;          $string=~s/([^\\])\#/$1\\\#/g;
    $string =~ s/_/\\_/g;              # _ -> \_
    $string =~ s/\^/\\\^{}/g;          # ^ -> \^{} 
     } else {      } else {
  $string=~s/\\/\\ensuremath{\\backslash}/g;   $string=~s/\\/\\ensuremath{\\backslash}/g;
  $string=~s/([^\\]|^)\%/$1\\\%/g;   $string=~s/\\\%|\%/\\\%/g;
  $string=~s/([^\\]|^)\$/$1\\\$/g;   $string=~s/\\{|{/\\{/g;
  $string=~s/([^\\])\_/$1\\_/g;   $string=~s/\\}|}/\\}/g;
  $string=~s/\$\$/\$\\\$/g;   $string=~s/\\ensuremath\\{\\backslash\\}/\\ensuremath{\\backslash}/g;
  $string=~s/\_\_/\_\\\_/g;   $string=~s/\\\$|\$/\\\$/g;
  $string=~s/\#\#/\#\\\#/g;   $string=~s/\\\_|\_/\\\_/g;
         $string=~s/([^\\]|^)(\~|\^)/$1\\$2\\strut /g;          $string=~s/([^\\]|^)(\~|\^)/$1\\$2\\strut /g;
  $string=~s/(>|<)/\\ensuremath\{$1\}/g; #more or less   $string=~s/(>|<)/\\ensuremath\{$1\}/g; #more or less
  $string=&Apache::lonprintout::character_chart($string);   $string=&Apache::lonprintout::character_chart($string);
  # any & or # leftover should be safe to just escape   # any & or # leftover should be safe to just escape
         $string=~s/([^\\]|^)\&/$1\\\&/g;   $string=~s/\\\&|\&/\\\&/g;
         $string=~s/([^\\]|^)\#/$1\\\#/g;   $string=~s/\\\#|\#/\\\#/g;
         $string=~s/\|/\$\\mid\$/g;          $string=~s/\|/\$\\mid\$/g;
 #single { or } How to escape?  #single { or } How to escape?
     }      }
Line 407  sub latex_special_symbols { Line 458  sub latex_special_symbols {
 }  }
   
 sub inner_xmlparse {  sub inner_xmlparse {
   my ($target,$stack,$parstack,$pars,$safeeval,$style_for_target)=@_;    my ($target,$stack,$parstack,$pars,$safeeval,$style_for_target,$start)=@_;
   my $finaloutput = '';    my $finaloutput = '';
   my $result;    my $result;
   my $token;    my $token;
   my $dontpop=0;    my $dontpop=0;
     my $lastdontpop;
     my $lastendtag;
     my $startredirection = $Apache::lonxml::redirection;
   while ( $#$pars > -1 ) {    while ( $#$pars > -1 ) {
     while ($token = $$pars['-1']->get_token) {      while ($token = $$pars['-1']->get_token) {
       if (($token->[0] eq 'T') || ($token->[0] eq 'C') ) {        if (($token->[0] eq 'T') || ($token->[0] eq 'C') ) {
Line 465  sub inner_xmlparse { Line 519  sub inner_xmlparse {
     while ($token->[1] ne $$stack['-1'] && ($#$stack > -1)) {      while ($token->[1] ne $$stack['-1'] && ($#$stack > -1)) {
  my $lasttag=$$stack[-1];   my $lasttag=$$stack[-1];
  if ($token->[1] =~ /^\Q$lasttag\E$/i) {   if ($token->[1] =~ /^\Q$lasttag\E$/i) {
     &Apache::lonxml::warning('Using tag &lt;/'.$token->[1].'&gt; on line '.$token->[3].' as end tag to &lt;'.$$stack[-1].'&gt;');      &Apache::lonxml::warning(&mt('Using tag [_1] on line [_2] as end tag to [_3]','&lt;/'.$token->[1].'&gt;','.$token->[3].','&lt;'.$$stack[-1].'&gt;'));
     last;      last;
  } else {   } else {
     &Apache::lonxml::warning('Found tag &lt;/'.$token->[1].'&gt; on line '.$token->[3].' when looking for &lt;/'.$$stack[-1].'&gt; in file');                      &Apache::lonxml::warning(&mt('Found tag [_1] on line [_2] when looking for [_3] in file.','&lt;/'.$token->[1].'&gt;',$token->[3],'&lt;/'.$$stack[-1].'&gt;'));
     &end_tag($stack,$parstack,$token);      &end_tag($stack,$parstack,$token);
  }   }
     }      }
Line 484  sub inner_xmlparse { Line 538  sub inner_xmlparse {
   if (!$Apache::lonxml::usestyle) {    if (!$Apache::lonxml::usestyle) {
       $extras=$Apache::lonxml::style_values;        $extras=$Apache::lonxml::style_values;
   }    }
  if ( $#$parstack > -1 ) {    if ( $#$parstack > -1 ) {
   $result=&Apache::run::evaluate($result,$safeeval,$extras.$$parstack[-1]);        $result=&Apache::run::evaluate($result,$safeeval,$extras.$$parstack[-1]);
  } else {    } else {
   $result= &Apache::run::evaluate($result,$safeeval,$extras);        $result= &Apache::run::evaluate($result,$safeeval,$extras);
  }            }
       }        }
       $Apache::lonxml::post_evaluate=1;        $Apache::lonxml::post_evaluate=1;
   
Line 506  sub inner_xmlparse { Line 560  sub inner_xmlparse {
       }        }
       $result = '';        $result = '';
   
       if ($token->[0] eq 'E' && !$dontpop) {        if ($token->[0] eq 'E') {
  &end_tag($stack,$parstack,$token);            if ($dontpop) {
                 $lastdontpop = $token;
             } else {
                 $lastendtag = $token->[1];
                 &end_tag($stack,$parstack,$token);
             }
       }        }
       $dontpop=0;        $dontpop=0;
     }      }
     if ($#$pars > -1) {      if ($#$pars > -1) {
  pop @$pars;   pop @$pars;
  pop @Apache::lonxml::pwd;   pop @Apache::lonxml::pwd;
     }      }
   }    }
   
     if (($#$stack == 0) && ($stack->[0] eq 'physnet') && ($target eq 'web') &&
         ($lastendtag eq 'LONCAPA_INTERNAL_TURN_STYLE_ON')) {
          if ((ref($lastdontpop) eq 'ARRAY') && ($lastdontpop->[1] eq 'physnet')) {
              &end_tag($stack,$parstack,$lastdontpop);
          }
      }
   
   # if ($target eq 'meta') {    # if ($target eq 'meta') {
   #   $finaloutput.=&endredirection;    #   $finaloutput.=&endredirection;
   # }    # }
   
     if ( $start && $target eq 'grade') { &endredirection(); }
     if ( $Apache::lonxml::redirection > $startredirection) {
         while ($Apache::lonxml::redirection > $startredirection) {
     $finaloutput .= &endredirection();
         }
     }
   if (($ENV{'QUERY_STRING'}) && ($target eq 'web')) {    if (($ENV{'QUERY_STRING'}) && ($target eq 'web')) {
     $finaloutput=&afterburn($finaloutput);      $finaloutput=&afterburn($finaloutput);
     }
     if ($target eq 'modified') {
   # if modfied, handle startpart and endpart
        $finaloutput=~s/\<startpartmarker[^\>]*\>(.*)\<endpartmarker[^\>]*\>/<part>$1<\/part>/gs;
   }        }    
   return $finaloutput;    return $finaloutput;
 }  }
Line 550  sub callsub { Line 625  sub callsub {
     }      }
   
     my $deleted=0;      my $deleted=0;
     $Apache::lonxml::curdepth=join('_',@Apache::lonxml::depthcounter);  
     if (($token->[0] eq 'S') && ($target eq 'modified')) {      if (($token->[0] eq 'S') && ($target eq 'modified')) {
       $deleted=&Apache::edit::handle_delete($space,$target,$token,$tagstack,        $deleted=&Apache::edit::handle_delete($space,$target,$token,$tagstack,
      $parstack,$parser,$safeeval,       $parstack,$parser,$safeeval,
Line 586  sub callsub { Line 660  sub callsub {
   } elsif ($token->[0] eq 'E') {    } elsif ($token->[0] eq 'E') {
     $currentstring = &Apache::edit::tag_end($target,$token);      $currentstring = &Apache::edit::tag_end($target,$token);
   }    }
  } elsif ($target eq 'modified') {   }
         }
         if ($target eq 'modified' && $nodefault eq '') {
     if ($currentstring eq '') {
         if ($token->[0] eq 'S') {
     $currentstring = $token->[4];
         } elsif ($token->[0] eq 'E') {
     $currentstring = $token->[2];
         } else {
     $currentstring = $token->[2];
         }
     }
   if ($token->[0] eq 'S') {    if ($token->[0] eq 'S') {
     $currentstring = $token->[4];        $currentstring.=&Apache::edit::handle_insert();
     $currentstring.=&Apache::edit::handle_insert();  
   } elsif ($token->[0] eq 'E') {    } elsif ($token->[0] eq 'E') {
     $currentstring = $token->[2];        $currentstring.=&Apache::edit::handle_insertafter($token->[1]);
             $currentstring.=&Apache::edit::handle_insertafter($token->[1]);  
   } else {  
     $currentstring = $token->[2];  
   }    }
  }  
       }        }
     }      }
     use strict 'refs';      use strict 'refs';
Line 604  sub callsub { Line 684  sub callsub {
   return $currentstring;    return $currentstring;
 }  }
   
   {
       my %state;
   
       sub init_state {
    undef(%state);
       }
       
       sub set_state {
    my ($key,$value) = @_;
    $state{$key} = $value;
    return $value;
       }
       sub get_state {
    my ($key) = @_;
    return $state{$key};
       }
   }
   
 sub setup_globals {  sub setup_globals {
   my ($request,$target)=@_;    my ($request,$target)=@_;
   $Apache::lonxml::request=$request;    $Apache::lonxml::request=$request;
   $Apache::lonxml::registered = 0;  
   @Apache::lonxml::htmlareafields=();  
   $errorcount=0;    $errorcount=0;
   $warningcount=0;    $warningcount=0;
     $Apache::lonxml::internal_error=0;
   $Apache::lonxml::default_homework_loaded=0;    $Apache::lonxml::default_homework_loaded=0;
   $Apache::lonxml::usestyle=1;    $Apache::lonxml::usestyle=1;
   &init_counter();    &init_counter();
     &clear_bubble_lines_for_part();
     &init_state();
     &set_state('target',$target);
   @Apache::lonxml::pwd=();    @Apache::lonxml::pwd=();
   @Apache::lonxml::extlinks=();    @Apache::lonxml::extlinks=();
     @script_var_displays=();
   @Apache::lonxml::ssi_info=();    @Apache::lonxml::ssi_info=();
   $Apache::lonxml::post_evaluate=1;    $Apache::lonxml::post_evaluate=1;
   $Apache::lonxml::warnings_error_header='';    $Apache::lonxml::warnings_error_header='';
     $Apache::lonxml::substitute_LaTeX_symbols = 1;
   if ($target eq 'meta') {    if ($target eq 'meta') {
     $Apache::lonxml::redirection = 0;      $Apache::lonxml::redirection = 0;
     $Apache::lonxml::metamode = 1;      $Apache::lonxml::metamode = 1;
Line 630  sub setup_globals { Line 732  sub setup_globals {
     $Apache::lonxml::evaluate = 1;      $Apache::lonxml::evaluate = 1;
     $Apache::lonxml::import = 1;      $Apache::lonxml::import = 1;
   } elsif ($target eq 'grade') {    } elsif ($target eq 'grade') {
     &startredirection;      &startredirection(); #ended in inner_xmlparse on exit
     $Apache::lonxml::metamode = 0;      $Apache::lonxml::metamode = 0;
     $Apache::lonxml::evaluate = 1;      $Apache::lonxml::evaluate = 1;
     $Apache::lonxml::import = 1;      $Apache::lonxml::import = 1;
Line 659  sub setup_globals { Line 761  sub setup_globals {
   
 sub init_safespace {  sub init_safespace {
   my ($target,$safeeval,$safehole,$safeinit) = @_;    my ($target,$safeeval,$safehole,$safeinit) = @_;
     $safeeval->reval('use LaTeX::Table;');
     $safeeval->deny_only(':dangerous');
     $safeeval->reval('use LONCAPA::LCMathComplex;');
     $safeeval->permit_only(":default");
   $safeeval->permit("entereval");    $safeeval->permit("entereval");
   $safeeval->permit(":base_math");    $safeeval->permit(":base_math");
   $safeeval->permit("sort");    $safeeval->permit("sort");
   $safeeval->permit("time");    $safeeval->permit("time");
     $safeeval->permit("caller");
     $safeeval->deny("rand");
     $safeeval->deny("srand");
   $safeeval->deny(":base_io");    $safeeval->deny(":base_io");
   $safehole->wrap(\&Apache::scripttag::xmlparse,$safeeval,'&xmlparse');    $safehole->wrap(\&Apache::scripttag::xmlparse,$safeeval,'&xmlparse');
   $safehole->wrap(\&Apache::outputtags::multipart,$safeeval,'&multipart');    $safehole->wrap(\&Apache::outputtags::multipart,$safeeval,'&multipart');
   $safehole->wrap(\&Apache::lonnet::EXT,$safeeval,'&EXT');    $safehole->wrap(\&Apache::lonnet::EXT,$safeeval,'&EXT');
   $safehole->wrap(\&Apache::chemresponse::chem_standard_order,$safeeval,    $safehole->wrap(\&Apache::chemresponse::chem_standard_order,$safeeval,
   '&chem_standard_order');    '&chem_standard_order');
     $safehole->wrap(\&Apache::response::check_status,$safeeval,'&check_status');
     $safehole->wrap(\&Apache::response::implicit_multiplication,$safeeval,'&implicit_multiplication');
   
     $safehole->wrap(\&Apache::lonmaxima::maxima_eval,$safeeval,'&maxima_eval');
     $safehole->wrap(\&Apache::lonmaxima::maxima_check,$safeeval,'&maxima_check');
     $safehole->wrap(\&Apache::lonmaxima::maxima_cas_formula_fix,$safeeval,
     '&maxima_cas_formula_fix');
   
     $safehole->wrap(\&Apache::lonr::r_eval,$safeeval,'&r_eval');
     $safehole->wrap(\&Apache::lonr::Rentry,$safeeval,'&Rentry');
     $safehole->wrap(\&Apache::lonr::Rarray,$safeeval,'&Rarray');
     $safehole->wrap(\&Apache::lonr::r_check,$safeeval,'&r_check');
     $safehole->wrap(\&Apache::lonr::r_cas_formula_fix,$safeeval,
                     '&r_cas_formula_fix');
    
     $safehole->wrap(\&Apache::caparesponse::capa_formula_fix,$safeeval,
     '&capa_formula_fix');
   
     $safehole->wrap(\&Apache::lonlocal::locallocaltime,$safeeval,
                     '&locallocaltime');
   
   $safehole->wrap(\&Math::Cephes::asin,$safeeval,'&asin');    $safehole->wrap(\&Math::Cephes::asin,$safeeval,'&asin');
   $safehole->wrap(\&Math::Cephes::acos,$safeeval,'&acos');    $safehole->wrap(\&Math::Cephes::acos,$safeeval,'&acos');
Line 713  sub init_safespace { Line 842  sub init_safespace {
   $safehole->wrap(\&Math::Cephes::stdtr ,$safeeval,'&stdtr' );    $safehole->wrap(\&Math::Cephes::stdtr ,$safeeval,'&stdtr' );
   $safehole->wrap(\&Math::Cephes::stdtri,$safeeval,'&stdtri');    $safehole->wrap(\&Math::Cephes::stdtri,$safeeval,'&stdtri');
   
     $safehole->wrap(\&Math::Cephes::Matrix::mat,$safeeval,'&mat');
     $safehole->wrap(\&Math::Cephes::Matrix::new,$safeeval,
     '&Math::Cephes::Matrix::new');
     $safehole->wrap(\&Math::Cephes::Matrix::coef,$safeeval,
     '&Math::Cephes::Matrix::coef');
     $safehole->wrap(\&Math::Cephes::Matrix::clr,$safeeval,
     '&Math::Cephes::Matrix::clr');
     $safehole->wrap(\&Math::Cephes::Matrix::add,$safeeval,
     '&Math::Cephes::Matrix::add');
     $safehole->wrap(\&Math::Cephes::Matrix::sub,$safeeval,
     '&Math::Cephes::Matrix::sub');
     $safehole->wrap(\&Math::Cephes::Matrix::mul,$safeeval,
     '&Math::Cephes::Matrix::mul');
     $safehole->wrap(\&Math::Cephes::Matrix::div,$safeeval,
     '&Math::Cephes::Matrix::div');
     $safehole->wrap(\&Math::Cephes::Matrix::inv,$safeeval,
     '&Math::Cephes::Matrix::inv');
     $safehole->wrap(\&Math::Cephes::Matrix::transp,$safeeval,
     '&Math::Cephes::Matrix::transp');
     $safehole->wrap(\&Math::Cephes::Matrix::simq,$safeeval,
     '&Math::Cephes::Matrix::simq');
     $safehole->wrap(\&Math::Cephes::Matrix::mat_to_vec,$safeeval,
     '&Math::Cephes::Matrix::mat_to_vec');
     $safehole->wrap(\&Math::Cephes::Matrix::vec_to_mat,$safeeval,
     '&Math::Cephes::Matrix::vec_to_mat');
     $safehole->wrap(\&Math::Cephes::Matrix::check,$safeeval,
     '&Math::Cephes::Matrix::check');
     $safehole->wrap(\&Math::Cephes::Matrix::check,$safeeval,
     '&Math::Cephes::Matrix::check');
   
 #  $safehole->wrap(\&Math::Cephes::new_fract,$safeeval,'&new_fract');  #  $safehole->wrap(\&Math::Cephes::new_fract,$safeeval,'&new_fract');
 #  $safehole->wrap(\&Math::Cephes::radd,$safeeval,'&radd');  #  $safehole->wrap(\&Math::Cephes::radd,$safeeval,'&radd');
 #  $safehole->wrap(\&Math::Cephes::rsub,$safeeval,'&rsub');  #  $safehole->wrap(\&Math::Cephes::rsub,$safeeval,'&rsub');
Line 741  sub init_safespace { Line 900  sub init_safespace {
   $safehole->wrap(\&Math::Random::random_set_seed_from_phrase,$safeeval,'&random_set_seed_from_phrase');    $safehole->wrap(\&Math::Random::random_set_seed_from_phrase,$safeeval,'&random_set_seed_from_phrase');
   $safehole->wrap(\&Math::Random::random_get_seed,$safeeval,'&random_get_seed');    $safehole->wrap(\&Math::Random::random_get_seed,$safeeval,'&random_get_seed');
   $safehole->wrap(\&Math::Random::random_set_seed,$safeeval,'&random_set_seed');    $safehole->wrap(\&Math::Random::random_set_seed,$safeeval,'&random_set_seed');
     $safehole->wrap(\&Apache::loncommon::languages,$safeeval,'&languages');
   $safehole->wrap(\&Apache::lonxml::error,$safeeval,'&LONCAPA_INTERNAL_ERROR');    $safehole->wrap(\&Apache::lonxml::error,$safeeval,'&LONCAPA_INTERNAL_ERROR');
   $safehole->wrap(\&Apache::lonxml::debug,$safeeval,'&LONCAPA_INTERNAL_DEBUG');    $safehole->wrap(\&Apache::lonxml::debug,$safeeval,'&LONCAPA_INTERNAL_DEBUG');
     $safehole->wrap(\&Apache::lonnet::logthis,$safeeval,'&LONCAPA_INTERNAL_LOGTHIS');
     $safehole->wrap(\&Apache::inputtags::finalizeawards,$safeeval,'&LONCAPA_INTERNAL_FINALIZEAWARDS');
   $safehole->wrap(\&Apache::caparesponse::get_sigrange,$safeeval,'&LONCAPA_INTERNAL_get_sigrange');    $safehole->wrap(\&Apache::caparesponse::get_sigrange,$safeeval,'&LONCAPA_INTERNAL_get_sigrange');
     $safehole->wrap(\&Apache::functionplotresponse::fpr_val,$safeeval,'&fpr_val');
     $safehole->wrap(\&Apache::functionplotresponse::fpr_f,$safeeval,'&fpr_f');
     $safehole->wrap(\&Apache::functionplotresponse::fpr_dfdx,$safeeval,'&fpr_dfdx');
     $safehole->wrap(\&Apache::functionplotresponse::fpr_d2fdx2,$safeeval,'&fpr_d2fdx2');
     $safehole->wrap(\&Apache::functionplotresponse::fpr_vectorcoords,$safeeval,'&fpr_vectorcoords');
     $safehole->wrap(\&Apache::functionplotresponse::fpr_objectcoords,$safeeval,'&fpr_objectcoords');
     $safehole->wrap(\&Apache::functionplotresponse::fpr_vectorlength,$safeeval,'&fpr_vectorlength');
     $safehole->wrap(\&Apache::functionplotresponse::fpr_vectorangle,$safeeval,'&fpr_vectorangle');
   
   #  use Data::Dumper;
   #  $safehole->wrap(\&Data::Dumper::Dumper,$safeeval,'&LONCAPA_INTERNAL_Dumper');
 #need to inspect this class of ops  #need to inspect this class of ops
 # $safeeval->deny(":base_orig");  # $safeeval->deny(":base_orig");
   $safeeval->permit("require");    $safeeval->permit("require");
   $safeinit .= ';$external::target="'.$target.'";';    $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.'";';  
   &Apache::lonxml::debug("Setting rndseed to $rndseed");  
   &Apache::run::run($safeinit,$safeeval);    &Apache::run::run($safeinit,$safeeval);
     my $rawrndseed = &initialize_rndseed($safeeval);
     if ($target eq 'grade') {
         $Apache::lonhomework::rawrndseed = $rawrndseed;
     }
   }
   
   sub clean_safespace {
       my ($safeeval) = @_;
       delete_package_recurse($safeeval->{Root});
   }
   
   sub delete_package_recurse {
        my ($package) = @_;
        my @subp;
        {
    no strict 'refs';
    while (my ($key,$val) = each(%{*{"$package\::"}})) {
        if (!defined($val)) { next; }
        local (*ENTRY) = $val;
        if (defined *ENTRY{HASH} && $key =~ /::$/ &&
    $key ne "main::" && $key ne "<none>::")
        {
    my ($p) = $package ne "main" ? "$package\::" : "";
    ($p .= $key) =~ s/::$//;
    push(@subp,$p);
        }
    }
        }
        foreach my $p (@subp) {
    delete_package_recurse($p);
        }
        Symbol::delete_package($package);
   }
   
   sub initialize_rndseed {
       my ($safeeval)=@_;
       my $rndseed;
       my ($symb,$courseid,$domain,$name) = &Apache::lonnet::whichuser();
       $rndseed=&Apache::lonnet::rndseed($symb,$courseid,$domain,$name);
       my $safeinit = '$external::randomseed="'.$rndseed.'";';
       &Apache::lonxml::debug("Setting rndseed to $rndseed");
       &Apache::run::run($safeinit,$safeeval);
       return $rndseed;
 }  }
   
 sub default_homework_load {  sub default_homework_load {
     my ($safeeval)=@_;      my ($safeeval)=@_;
     &Apache::lonxml::debug('Loading default_homework');      &Apache::lonxml::debug('Loading default_homework');
     my $default=&Apache::lonnet::getfile('/home/httpd/html/res/adm/includes/default_homework.lcpm');      my $default=&Apache::lonnet::getfile($Apache::lonnet::perlvar{'lonIncludes'}.
                                            '/default_homework.lcpm');
     if ($default eq -1) {      if ($default eq -1) {
  &Apache::lonxml::error("<b>Unable to find <i>default_homework.lcpm</i></b>");   &Apache::lonxml::error("<b>Unable to find <i>default_homework.lcpm</i></b>");
     } else {      } else {
Line 770  sub default_homework_load { Line 980  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;  my $metamode_was;
 sub startredirection {  sub startredirection {
     if (!$Apache::lonxml::redirection) {      if (!$Apache::lonxml::redirection) {
Line 782  sub startredirection { Line 1014  sub startredirection {
   
 sub endredirection {  sub endredirection {
     if (!$Apache::lonxml::redirection) {      if (!$Apache::lonxml::redirection) {
  &Apache::lonxml::error("Endredirection was called, before a startredirection, perhaps you have unbalanced tags. Some debuging information:".join ":",caller);   &Apache::lonxml::error("Endredirection was called before a startredirection, perhaps you have unbalanced tags. Some debugging information:".join ":",caller);
  return '';   return '';
     }      }
     $Apache::lonxml::redirection--;      $Apache::lonxml::redirection--;
Line 791  sub endredirection { Line 1023  sub endredirection {
     }      }
     pop @Apache::lonxml::outputstack;      pop @Apache::lonxml::outputstack;
 }  }
   sub in_redirection {
       return ($Apache::lonxml::redirection > 0)
   }
   
 sub end_tag {  sub end_tag {
   my ($tagstack,$parstack,$token)=@_;    my ($tagstack,$parstack,$token)=@_;
Line 801  sub end_tag { Line 1036  sub end_tag {
   
 sub initdepth {  sub initdepth {
   @Apache::lonxml::depthcounter=();    @Apache::lonxml::depthcounter=();
   $Apache::lonxml::depth=-1;    undef($Apache::lonxml::last_depth_count);
   $Apache::lonxml::olddepth=-1;  
 }  }
   
   
   my @timers;
   my $lasttime;
   # @Apache::lonxml::depthcounter -> count of tags that exist so
   #                                  far at each level
   # $Apache::lonxml::last_depth_count -> when ascending, need to
   # remember the count for the level below the current level (for
   # example going from 1_2 -> 1 -> 1_3 need to remember the 2 )
   
 sub increasedepth {  sub increasedepth {
   my ($token) = @_;    my ($token) = @_;
   $Apache::lonxml::depth++;    push(@Apache::lonxml::depthcounter,$Apache::lonxml::last_depth_count+1);
   $Apache::lonxml::depthcounter[$Apache::lonxml::depth]++;    undef($Apache::lonxml::last_depth_count);
   if ($Apache::lonxml::depthcounter[$Apache::lonxml::depth]==1) {    my $time;
     $Apache::lonxml::olddepth=$Apache::lonxml::depth;    if ($Apache::lonxml::debug eq "1") {
         push(@timers,[&gettimeofday()]);
         $time=&tv_interval($lasttime);
         $lasttime=[&gettimeofday()];
   }    }
   my $curdepth=join('_',@Apache::lonxml::depthcounter);    my $spacing='  'x($#Apache::lonxml::depthcounter);
   &Apache::lonxml::debug("s $Apache::lonxml::depth : $Apache::lonxml::olddepth : $curdepth : $token->[1]\n");    $Apache::lonxml::curdepth=join('_',@Apache::lonxml::depthcounter);
   #  &Apache::lonxml::debug("s$spacing$Apache::lonxml::depth : $Apache::lonxml::olddepth : $Apache::lonxml::curdepth : $token->[1] : $time");
 #print "<br />s $Apache::lonxml::depth : $Apache::lonxml::olddepth : $curdepth : $token->[1]\n";  #print "<br />s $Apache::lonxml::depth : $Apache::lonxml::olddepth : $curdepth : $token->[1]\n";
 }  }
   
 sub decreasedepth {  sub decreasedepth {
   my ($token) = @_;    my ($token) = @_;
   $Apache::lonxml::depth--;    if (  $#Apache::lonxml::depthcounter == -1) {
   if ($Apache::lonxml::depth<$Apache::lonxml::olddepth-1) {        &Apache::lonxml::warning(&mt("Missing tags, unable to properly run file."));
     $#Apache::lonxml::depthcounter--;  
     $Apache::lonxml::olddepth=$Apache::lonxml::depth+1;  
   }    }
   if (  $Apache::lonxml::depth < -1) {    $Apache::lonxml::last_depth_count = pop(@Apache::lonxml::depthcounter);
     &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 $curdepth=join('_',@Apache::lonxml::depthcounter);    my $spacing='  'x($#Apache::lonxml::depthcounter);
   &Apache::lonxml::debug("e $Apache::lonxml::depth : $Apache::lonxml::olddepth : $token->[1] : $curdepth\n");    $Apache::lonxml::curdepth = join('_',@Apache::lonxml::depthcounter);
   #  &Apache::lonxml::debug("e$spacing$Apache::lonxml::depth : $Apache::lonxml::olddepth : $Apache::lonxml::curdepth : $token->[1] : $time : ".&tv_interval($timer));
 #print "<br />e $Apache::lonxml::depth : $Apache::lonxml::olddepth : $token->[1] : $curdepth\n";  #print "<br />e $Apache::lonxml::depth : $Apache::lonxml::olddepth : $token->[1] : $curdepth\n";
 }  }
   
   sub get_id {
       my ($parstack,$safeeval)=@_;
       my $id= &Apache::lonxml::get_param('id',$parstack,$safeeval);
       if ($env{'request.state'} eq 'construct' && $id =~ /([._]|[^\w\d\s[:punct:]])/) {
    &error(&mt('ID [_1] contains invalid characters. IDs are only allowed to contain letters, numbers, spaces and -','"<tt>'.$id.'</tt>"'));
       }
       if ($id =~ /^\s*$/) { $id = $Apache::lonxml::curdepth; }
       return $id;
   }
   
 sub get_all_text_unbalanced {  sub get_all_text_unbalanced {
 #there is a copy of this in lonpublisher.pm  #there is a copy of this in lonpublisher.pm
     my($tag,$pars)= @_;      my($tag,$pars)= @_;
Line 841  sub get_all_text_unbalanced { Line 1101  sub get_all_text_unbalanced {
     $tag='<'.$tag.'>';      $tag='<'.$tag.'>';
     while ($token = $$pars[-1]->get_token) {      while ($token = $$pars[-1]->get_token) {
  if (($token->[0] eq 'T')||($token->[0] eq 'C')||($token->[0] eq 'D')) {   if (($token->[0] eq 'T')||($token->[0] eq 'C')||($token->[0] eq 'D')) {
     $result.=$token->[1];      if ($token->[0] eq 'T' && $token->[2]) {
    $result.='<![CDATA['.$token->[1].']]>';
       } else {
    $result.=$token->[1];
       }
  } elsif ($token->[0] eq 'PI') {   } elsif ($token->[0] eq 'PI') {
     $result.=$token->[2];      $result.=$token->[2];
  } elsif ($token->[0] eq 'S') {   } elsif ($token->[0] eq 'S') {
Line 859  sub get_all_text_unbalanced { Line 1123  sub get_all_text_unbalanced {
  }   }
     }      }
     return $result      return $result
   
 }  }
   
   #########################################################################
   #                                                                       #
   #           bubble line counter management                              #
   #                                                                       #
   #########################################################################
   
   =pod
   
   For bubble grading mode and exam bubble printing mode, the tracking of
   the current 'bubble line number' is stored in the %env element
   'form.counter', and is modifed and handled by the following routines.
   
   The value of it is stored in $Apache:lonxml::counter when live and
   stored back to env after done.
   
   =item &increment_counter($increment, $part_response);
   
   Increments the internal counter environment variable a specified amount
   
   Optional Arguments:
     $increment - amount to increment by (defaults to 1)
                  Also 1 if the value is negative or zero.
     $part_response - A concatenation of the part and response id
                      identifying exactly what is being 'answered'.
   
   
   =cut
   
 sub increment_counter {  sub increment_counter {
     my ($increment) = @_;      my ($increment, $part_response) = @_;
     if (defined($increment) && $increment gt 0) {      if ($env{'form.grade_noincrement'}) { return; }
  $Apache::lonxml::counter+=$increment;      if (!defined($increment) || $increment le 0) {
     } else {   $increment = 1;
  $Apache::lonxml::counter++;      }
       $Apache::lonxml::counter += $increment;
   
       # If the caller supplied the response_id parameter, 
       # Maintain its counter.. creating if necessary.
   
       if (defined($part_response)) {
    if (!defined($Apache::lonxml::counters_per_part{$part_response})) {
       $Apache::lonxml::counters_per_part{$part_response} = 0;
    }
    $Apache::lonxml::counters_per_part{$part_response} += $increment;
    my $new_value = $Apache::lonxml::counters_per_part{$part_response};
     }      }
   
     $Apache::lonxml::counter_changed=1;      $Apache::lonxml::counter_changed=1;
 }  }
   
   =pod
   
   =item &init_counter($increment);
   
   Initialize the internal counter environment variable
   
   =cut
   
 sub init_counter {  sub init_counter {
     if (defined($ENV{'form.counter'})) {      if ($env{'request.state'} eq 'construct') {
  $Apache::lonxml::counter=$ENV{'form.counter'};   $Apache::lonxml::counter=1;
    $Apache::lonxml::counter_changed=1;
       } elsif (defined($env{'form.counter'})) {
    $Apache::lonxml::counter=$env{'form.counter'};
  $Apache::lonxml::counter_changed=0;   $Apache::lonxml::counter_changed=0;
     } else {      } else {
  $Apache::lonxml::counter=1;   $Apache::lonxml::counter=1;
Line 882  sub init_counter { Line 1198  sub init_counter {
 }  }
   
 sub store_counter {  sub store_counter {
     &Apache::lonnet::appenv(('form.counter' => $Apache::lonxml::counter));      &Apache::lonnet::appenv({'form.counter' => $Apache::lonxml::counter});
       $Apache::lonxml::counter_changed=0;
     return '';      return '';
 }  }
   
   {
       my $state;
       sub clear_problem_counter {
    undef($state);
    &Apache::lonnet::delenv('form.counter');
    &Apache::lonxml::init_counter();
    &Apache::lonxml::store_counter();
       }
   
       sub remember_problem_counter {
    &Apache::lonnet::transfer_profile_to_env(undef,undef,1);
    $state = $env{'form.counter'};
       }
   
       sub restore_problem_counter {
    if (defined($state)) {
       &Apache::lonnet::appenv({'form.counter' => $state});
    }
       }
       sub get_problem_counter {
    if ($Apache::lonxml::counter_changed) { &store_counter() }
    &Apache::lonnet::transfer_profile_to_env(undef,undef,1);
    return $env{'form.counter'};
       }
   }
   
   =pod
   
   =item  bubble_lines_for_part(part_response)
   
   Returns the number of lines required to get a response for
   $part_response (this is just $Apache::lonxml::counters_per_part{$part_response}
   
   =cut
   
   sub bubble_lines_for_part {
       my ($part_response) = @_;
   
       if (!defined($Apache::lonxml::counters_per_part{$part_response})) {
    return 0;
       } else {
    return $Apache::lonxml::counters_per_part{$part_response};
       }
   }
   
   =pod
   
   =item clear_bubble_lines_for_part
   
   Clears the hash of bubble lines per part.  If a caller
   needs to analyze several resources this should be called between
   resources to reset the hash for each problem being analyzed.
   
   =cut
   
   sub clear_bubble_lines_for_part {
       undef(%Apache::lonxml::counters_per_part);
   }
   
   =pod
   
   =item set_bubble_lines(part_response, value)
   
   If there is a problem part, that for whatever reason
   requires bubble lines that are not
   the same as the counter increment, it can call this sub during
   analysis to set its hash value explicitly.
   
   =cut
   
   sub set_bubble_lines {
       my ($part_response, $value) = @_;
   
       $Apache::lonxml::counters_per_part{$part_response} = $value;
   }
   
   =pod
   
   =item get_bubble_line_hash
   
   Returns the current bubble line hash.  This is assumed to 
   be small so we return a copy
   
   
   =cut
   
   sub get_bubble_line_hash {
       return %Apache::lonxml::counters_per_part;
   }
   
   
   #--------------------------------------------------
   
 sub get_all_text {  sub get_all_text {
     my($tag,$pars,$style)= @_;      my($tag,$pars,$style)= @_;
     my $gotfullstack=1;      my $gotfullstack=1;
Line 907  sub get_all_text { Line 1317  sub get_all_text {
     while (($depth >=0) && ($token = $$pars[-1]->get_token)) {      while (($depth >=0) && ($token = $$pars[-1]->get_token)) {
  #&Apache::lonxml::debug("e token:$token->[0]:$depth:$token->[1]:".$#$pars.":".$#Apache::lonxml::pwd);   #&Apache::lonxml::debug("e token:$token->[0]:$depth:$token->[1]:".$#$pars.":".$#Apache::lonxml::pwd);
  if (($token->[0] eq 'T')||($token->[0] eq 'C')||($token->[0] eq 'D')) {   if (($token->[0] eq 'T')||($token->[0] eq 'C')||($token->[0] eq 'D')) {
     $result.=$token->[1];      if ($token->[2]) {
    $result.='<![CDATA['.$token->[1].']]>';
       } else {
    $result.=$token->[1];
       }
  } elsif ($token->[0] eq 'PI') {   } elsif ($token->[0] eq 'PI') {
     $result.=$token->[2];      $result.=$token->[2];
  } elsif ($token->[0] eq 'S') {   } elsif ($token->[0] eq 'S') {
Line 959  sub get_all_text { Line 1373  sub get_all_text {
  #&Apache::lonxml::debug("s token:$token->[0]:$depth:$token->[1]");   #&Apache::lonxml::debug("s token:$token->[0]:$depth:$token->[1]");
  if (($token->[0] eq 'T')||($token->[0] eq 'C')||   if (($token->[0] eq 'T')||($token->[0] eq 'C')||
     ($token->[0] eq 'D')) {      ($token->[0] eq 'D')) {
     $result.=$token->[1];      if ($token->[2]) {
    $result.='<![CDATA['.$token->[1].']]>';
       } else {
    $result.=$token->[1];
       }
  } elsif ($token->[0] eq 'PI') {   } elsif ($token->[0] eq 'PI') {
     $result.=$token->[2];      $result.=$token->[2];
  } elsif ($token->[0] eq 'S') {   } elsif ($token->[0] eq 'S') {
Line 987  sub get_all_text { Line 1405  sub get_all_text {
 sub newparser {  sub newparser {
   my ($parser,$contentref,$dir) = @_;    my ($parser,$contentref,$dir) = @_;
   push (@$parser,HTML::LCParser->new($contentref));    push (@$parser,HTML::LCParser->new($contentref));
   $$parser['-1']->xml_mode('1');    $$parser[-1]->xml_mode(1);
     $$parser[-1]->marked_sections(1);
   if ( $dir eq '' ) {    if ( $dir eq '' ) {
     push (@Apache::lonxml::pwd, $Apache::lonxml::pwd[$#Apache::lonxml::pwd]);      push (@Apache::lonxml::pwd, $Apache::lonxml::pwd[$#Apache::lonxml::pwd]);
   } else {    } else {
Line 996  sub newparser { Line 1415  sub newparser {
 }  }
   
 sub parstring {  sub parstring {
   my ($token) = @_;      my ($token) = @_;
   my $temp='';      my (@vars,@values);
   foreach (@{$token->[3]}) {      foreach my $attr (@{$token->[3]}) {
     unless ($_=~/\W/) {   if ($attr!~/\W/) {
       my $val=$token->[2]->{$_};      my $val=$token->[2]->{$attr};
       $val =~ s/([\%\@\\\"\'])/\\$1/g;      $val =~ s/([\%\@\\\"\'])/\\$1/g;
       #if ($val =~ m/^[\%\@]/) { $val="\\".$val; }      $val =~ s/(\$[^\{a-zA-Z_])/\\$1/g;
       $temp .= "my \$$_=\"$val\";";      $val =~ s/(\$)$/\\$1/;
       #if ($val =~ m/^[\%\@]/) { $val="\\".$val; }
       push(@vars,"\$$attr");
       push(@values,"\"$val\"");
    }
       }
       my $var_init = 
    (@vars) ? 'my ('.join(',',@vars).') = ('.join(',',@values).');'
           : '';
       return $var_init;
   }
   
   sub extlink {
       my ($res,$exact)=@_;
       if (!$exact) {
    $res=&Apache::lonnet::hreflocation($Apache::lonxml::pwd[-1],$res);
     }      }
   }      push(@Apache::lonxml::extlinks,$res);
   return $temp;  
 }  }
   
 sub writeallows {  sub writeallows {
     unless ($#extlinks>=0) { return; }      unless ($#extlinks>=0) { return; }
     my $thisurl='/res/'.&Apache::lonnet::declutter(shift);      my $thisurl = &Apache::lonnet::clutter(shift);
     if ($ENV{'httpref.'.$thisurl}) {      if ($env{'httpref.'.$thisurl}) {
  $thisurl=$ENV{'httpref.'.$thisurl};   $thisurl=$env{'httpref.'.$thisurl};
     }      }
     my $thisdir=$thisurl;      my $thisdir=$thisurl;
     $thisdir=~s/\/[^\/]+$//;      $thisdir=~s/\/[^\/]+$//;
     my %httpref=();      my %httpref=();
     foreach (@extlinks) {      foreach (@extlinks) {
        $httpref{'httpref.'.         $httpref{'httpref.'.
          &Apache::lonnet::hreflocation($thisdir,$_)}=$thisurl;           &Apache::lonnet::hreflocation($thisdir,&unescape($_))}=$thisurl;
     }      }
     @extlinks=();      @extlinks=();
     &Apache::lonnet::appenv(%httpref);      &Apache::lonnet::appenv(\%httpref);
 }  }
   
 sub register_ssi {  sub register_ssi {
Line 1039  sub do_registered_ssi { Line 1472  sub do_registered_ssi {
  &Apache::lonnet::ssi($url,%form);   &Apache::lonnet::ssi($url,%form);
     }      }
 }  }
   
   sub add_script_result {
       my ($display) = @_;
       if ($display ne '') {
           push(@script_var_displays, $display);
       }
   }
   
 #  #
 # Afterburner handles anchors, highlights and links  # Afterburner handles anchors, highlights and links
 #  #
Line 1046  sub afterburn { Line 1487  sub afterburn {
     my $result=shift;      my $result=shift;
     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},      &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
     ['highlight','anchor','link']);      ['highlight','anchor','link']);
     if ($ENV{'form.highlight'}) {      if ($env{'form.highlight'}) {
        foreach (split(/\,/,$ENV{'form.highlight'})) {         foreach (split(/\,/,$env{'form.highlight'})) {
            my $anchorname=$_;             my $anchorname=$_;
    my $matchthis=$anchorname;     my $matchthis=$anchorname;
            $matchthis=~s/\_+/\\s\+/g;             $matchthis=~s/\_+/\\s\+/g;
            $result=~s/(\Q$matchthis\E)/\<font color=\"red\"\>$1\<\/font\>/gs;             $result=~s/(\Q$matchthis\E)/\<font color=\"red\"\>$1\<\/font\>/gs;
        }         }
     }      }
     if ($ENV{'form.link'}) {      if ($env{'form.link'}) {
        foreach (split(/\,/,$ENV{'form.link'})) {         foreach (split(/\,/,$env{'form.link'})) {
            my ($anchorname,$linkurl)=split(/\>/,$_);             my ($anchorname,$linkurl)=split(/\>/,$_);
    my $matchthis=$anchorname;     my $matchthis=$anchorname;
            $matchthis=~s/\_+/\\s\+/g;             $matchthis=~s/\_+/\\s\+/g;
            $result=~s/(\Q$matchthis\E)/\<a href=\"$linkurl\"\>$1\<\/a\>/gs;             $result=~s/(\Q$matchthis\E)/\<a href=\"$linkurl\"\>$1\<\/a\>/gs;
        }         }
     }      }
     if ($ENV{'form.anchor'}) {      if ($env{'form.anchor'}) {
         my $anchorname=$ENV{'form.anchor'};          my $anchorname=$env{'form.anchor'};
  my $matchthis=$anchorname;   my $matchthis=$anchorname;
         $matchthis=~s/\_+/\\s\+/g;          $matchthis=~s/\_+/\\s\+/g;
         $result=~s/(\Q$matchthis\E)/\<a name=\"$anchorname\"\>$1\<\/a\>/s;          $result=~s/(\Q$matchthis\E)/\<a name=\"$anchorname\"\>$1\<\/a\>/s;
Line 1084  sub storefile { Line 1525  sub storefile {
         $fh->close();          $fh->close();
         return 1;          return 1;
     } else {      } else {
  &warning("Unable to save file $file");   &warning(&mt('Unable to save file [_1]','<tt>'.$file.'</tt>'));
  return 0;   return 0;
     }      }
 }  }
Line 1093  sub createnewhtml { Line 1534  sub createnewhtml {
     my $title=&mt('Title of document goes here');      my $title=&mt('Title of document goes here');
     my $body=&mt('Body of document goes here');      my $body=&mt('Body of document goes here');
     my $filecontents=(<<SIMPLECONTENT);      my $filecontents=(<<SIMPLECONTENT);
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml/11/DTD/xhtml11.dtd">  
 <html>  <html>
 <head>  <head>
 <title>$title</title>  <title>$title</title>
Line 1118  SIMPLECONTENT Line 1558  SIMPLECONTENT
   return $filecontents;    return $filecontents;
 }  }
   
   sub createnewjs {
       my $filecontents=(<<SIMPLECONTENT);
   <script type="text/javascript" language="Javascript">
   
   </script>
   SIMPLECONTENT
       return $filecontents;
   }
   
   sub verify_html {
       my ($filecontents)=@_;
       my ($is_html,$is_xml,$is_physnet);
       if ($filecontents =~/(?:\<|\&lt\;)\?xml[^\<]*\?(?:\>|\&gt\;)/is) {
           $is_xml = 1;
       } elsif ($filecontents =~/(?:\<|\&lt\;)html(?:\s+[^\<]+|\s*)(?:\>|\&gt\;)/is) {
           $is_html = 1;
       } elsif ($filecontents =~/(?:\<|\&lt\;)physnet[^\<]*(?:\>|\&gt\;)/is) {
           $is_physnet = 1;
       }
       unless ($is_xml || $is_html || $is_physnet) {
           return &mt('File does not have [_1] or [_2] starting tag','&lt;html&gt;','&lt;?xml ?&gt;');
       }
       if ($is_html) {
           if ($filecontents!~/(?:\<|\&lt\;)\/html(?:\>|\&gt\;)/is) {
               return &mt('File does not have [_1] ending tag','&lt;html&gt;');
           }
           if ($filecontents!~/(?:\<|\&lt\;)(?:body|frameset)[^\<]*(?:\>|\&gt\;)/is) {
               return &mt('File does not have [_1] or [_2] starting tag','&lt;body&gt;','&lt;frameset&gt;');
           }
           if ($filecontents!~/(?:\<|\&lt\;)\/(?:body|frameset)[^\<]*(?:\>|\&gt\;)/is) {
               return &mt('File does not have [_1] or [_2] ending tag','&lt;body&gt;','&lt;frameset&gt;');
           }
       }
       return '';
   }
   
   sub renderingoptions {
       my %langchoices=('' => '');
       foreach (&Apache::loncommon::languageids()) {
           if (&Apache::loncommon::supportedlanguagecode($_)) {
               $langchoices{&Apache::loncommon::supportedlanguagecode($_)}
                          = &Apache::loncommon::plainlanguagedescription($_);
           }
       }
       my $output;
       unless ($env{'form.forceedit'}) {
          $output .=
              '<span class="LC_nobreak">'.
              &mt('Language:').' '.
              &Apache::loncommon::select_form(
                  $env{'form.languages'},
                  'languages',
                  {&Apache::lonlocal::texthash(%langchoices)}).
              '</span>';
       }
       $output .=
        ' <span class="LC_nobreak">'.
          &mt('Math Rendering:').' '.
          &Apache::loncommon::select_form(
              $env{'form.texengine'},
              'texengine',
              {&Apache::lonlocal::texthash
                  (''        => '',
                   'tth'     => 'tth (TeX to HTML)',
                   'MathJax' => 'MathJax',
                   'mimetex' => 'mimetex (Convert to Images)')}).
        '</span>';
       return $output;
   }
   
 sub inserteditinfo {  sub inserteditinfo {
       my ($result,$filecontents,$filetype)=@_;        my ($filecontents,$filetype,$filename,$symb,$itemtitle,$folderpath,$uri,$action) = @_;
       $filecontents = &HTML::Entities::encode($filecontents,'<>&"');        $filecontents = &HTML::Entities::encode($filecontents,'<>&"');
 #      my $editheader='<a href="#editsection">Edit below</a><hr />';  
       my $xml_help = '';        my $xml_help = '';
       my $initialize='';        my $initialize='';
         my $textarea_id = 'filecont';
         my ($dragmath_button,$deps_button,$context,$cnum,$cdom,$add_to_onload,
             $add_to_onresize,$init_dragmath);
         $initialize=&Apache::lonhtmlcommon::spellheader();
       if ($filetype eq 'html') {        if ($filetype eq 'html') {
   my $addbuttons=&Apache::lonhtmlcommon::htmlareaaddbuttons();            if ($env{'request.course.id'}) {
   $initialize=&Apache::lonhtmlcommon::htmlareaheaders().                $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
       &Apache::lonhtmlcommon::spellheader().(<<FULLPAGE);                $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                 if ($uri =~ m{^\Q/uploaded/$cdom/$cnum/portfolio/syllabus/\E}) {
                     $context = 'syllabus';
                 }
             }
             if (&Apache::lonhtmlcommon::htmlareabrowser()) {
         my $lang = &Apache::lonhtmlcommon::htmlarea_lang();
                 my %textarea_args = (
                                       fullpage => 'true',
                                       dragmath => 'math',
                                     );
                 $initialize .= &Apache::lonhtmlcommon::htmlareaselectactive(\%textarea_args);
                 if ($context eq 'syllabus') {
                     $init_dragmath = "editmath_visibility('filecont','none')";
                 }
             }
         }
         $initialize .= (<<FULLPAGE);
 <script type="text/javascript">  <script type="text/javascript">
 $addbuttons  // <![CDATA[
   
     HTMLArea.loadPlugin("FullPage");  
   
     function initDocument() {      function initDocument() {
  var editor=new HTMLArea("filecont",config);   resize_textarea('$textarea_id','LC_aftertextarea');
  editor.registerPlugin(FullPage);          $init_dragmath
  editor.generate();  
     }      }
   // ]]>
 </script>  </script>
 FULLPAGE  FULLPAGE
           $result=~s/\<body([^\>]*)\>/\<body onload="initDocument()" $1\>/i;        my $textareaclass;
   $xml_help=&Apache::loncommon::helpLatexCheatsheet();        if ($filetype eq 'html') {
             if ($context eq 'syllabus') {
                 $deps_button = &Apache::lonhtmlcommon::dependencies_button()."\n";
                 $initialize .=
                     &Apache::lonhtmlcommon::dependencycheck_js(undef,&mt('Syllabus'),
                                                                $uri,undef,
                                                                "/public/$cdom/$cnum/syllabus").
                     "\n";
                 if (&Apache::lonhtmlcommon::htmlareabrowser()) {
                     $textareaclass = 'class="LC_richDefaultOn"';
                 }
             } elsif ($symb || $folderpath) {
                 $deps_button = &Apache::lonhtmlcommon::dependencies_button()."\n";
                 $initialize .=
                     &Apache::lonhtmlcommon::dependencycheck_js($symb,$itemtitle,
                                                                undef,$folderpath,$uri)."\n";
             }
             $dragmath_button = '<span id="math_filecont">'.&Apache::lonhtmlcommon::dragmath_button('filecont',1).'</span>';
             $initialize .= "\n".&Apache::lonhtmlcommon::dragmath_js('EditMathPopup');
       }        }
       my $cleanbut = '';        $add_to_onload = 'initDocument();';
         $add_to_onresize = "resize_textarea('$textarea_id','LC_aftertextarea');";
   
       if ($filetype eq 'html') {        if ($filetype eq 'html') {
   $cleanbut='<input type="submit" name="attemptclean" value="'.            my $not_author;
       &mt('Save and then attempt to clean HTML').'" />';            if ($uri =~ m{^/uploaded/}) {
                 $not_author = 1;
             }
     $xml_help=&Apache::loncommon::helpLatexCheatsheet(undef,undef,$not_author);
       }        }
   
       my $titledisplay=&display_title();        my $titledisplay=&display_title();
       my %lt=&Apache::lonlocal::texthash('st' => 'Save this',        my %lt=&Apache::lonlocal::texthash('st' => 'Save and Edit',
  'vi' => 'View',   'vi' => 'Save and View',
    'dv' => 'Discard Edits and View',
    'un' => 'undo',
  'ed' => 'Edit');   'ed' => 'Edit');
       my $buttons=(<<BUTTONS);        my $spelllink = &Apache::lonhtmlcommon::spelllink('xmledit','filecont');
 $cleanbut        my $textarea_events = &Apache::edit::element_change_detection();
 <input type="submit" name="savethisfile" accesskey="s"  value="$lt{'st'}" />        my $form_events     = &Apache::edit::form_change_detection();
 <input type="submit" name="viewmode" accesskey="v" value="$lt{'vi'}" />        my $htmlerror;
 BUTTONS        if ($filetype eq 'html') {
       $buttons.=&Apache::lonhtmlcommon::spelllink('xmledit','filecont');            $htmlerror=&verify_html($filecontents);
             if ($htmlerror) {
                 $htmlerror='<span class="LC_error">'.$htmlerror.'</span>';
             }
             if (&Apache::lonhtmlcommon::htmlareabrowser()) {
                 unless ($textareaclass) {
                     $textareaclass = 'class="LC_richDefaultOff"';
                 }
             }
         }
         my $undo;
         unless ($uri =~ m{^/uploaded/}) {
             $undo = '<input type="submit" name="Undo" accesskey="u" value="'.$lt{'un'}.'" />'."\n";
         }
       my $editfooter=(<<ENDFOOTER);        my $editfooter=(<<ENDFOOTER);
 $initialize  $initialize
 <hr />  
 <a name="editsection" />  <a name="editsection" />
 <form method="post" name="xmledit">  <form $form_events method="post" name="xmledit" action="$action">
 $xml_help    <div class="LC_edit_problem_editxml_header">
 <input type="hidden" name="editmode" value="$lt{'ed'}" />      <table class="LC_edit_problem_header_title"><tr><td>
 $buttons<br />          $filename
 <textarea cols="80" rows="44" name="filecont" id="filecont">$filecontents</textarea>        </td><td align="right">
 <br />$buttons          $xml_help
 <br />        </td></tr>
       </table>
       <div class="LC_edit_problem_discards">
         <input type="submit" name="discardview" accesskey="d" value="$lt{'dv'}" />
         $undo $htmlerror $deps_button $dragmath_button
       </div>
       <div class="LC_edit_problem_saves">
         <input type="submit" name="savethisfile" accesskey="s" value="$lt{'st'}" />
         <input type="submit" name="viewmode" accesskey="v" value="$lt{'vi'}" />
       </div>
     </div>
     <textarea $textarea_events style="width:100%" cols="80" rows="44" name="filecont" id="filecont" $textareaclass>$filecontents</textarea><br />$spelllink
     <div id="LC_aftertextarea">
       <br />
       $titledisplay
     </div>
 </form>  </form>
 $titledisplay  
 </body>  
 ENDFOOTER  ENDFOOTER
 #      $result=~s/(\<body[^\>]*\>)/$1$editheader/is;        return ($editfooter,$add_to_onload,$add_to_onresize);;
       $result=~s/(\<\/body\>)/$editfooter/is;  
       return $result;  
 }  }
   
 sub get_target {  sub get_target {
   my $viewgrades=&Apache::lonnet::allowed('vgr',$ENV{'request.course.id'});    my $viewgrades=&Apache::lonnet::allowed('vgr',$env{'request.course.id'});
   if ( $ENV{'request.state'} eq 'published') {    if ( $env{'request.state'} eq 'published') {
     if ( defined($ENV{'form.grade_target'})      if ( defined($env{'form.grade_target'})
  && ($viewgrades == 'F' )) {   && ($viewgrades == 'F' )) {
       return ($ENV{'form.grade_target'});        return ($env{'form.grade_target'});
     } elsif (defined($ENV{'form.grade_target'})) {      } elsif (defined($env{'form.grade_target'})) {
       if (($ENV{'form.grade_target'} eq 'web') ||        if (($env{'form.grade_target'} eq 'web') ||
   ($ENV{'form.grade_target'} eq 'tex') ) {    ($env{'form.grade_target'} eq 'tex') ) {
  return $ENV{'form.grade_target'}   return $env{'form.grade_target'}
       } else {        } else {
  return 'web';   return 'web';
       }        }
     } else {      } else {
       return 'web';        return 'web';
     }      }
   } elsif ($ENV{'request.state'} eq 'construct') {    } elsif ($env{'request.state'} eq 'construct') {
     if ( defined($ENV{'form.grade_target'})) {      if ( defined($env{'form.grade_target'})) {
       return ($ENV{'form.grade_target'});        return ($env{'form.grade_target'});
     } else {      } else {
       return 'web';        return 'web';
     }      }
Line 1208  sub get_target { Line 1783  sub get_target {
   
 sub handler {  sub handler {
     my $request=shift;      my $request=shift;
       
     my $target=&get_target();      my $target=&get_target();
       $Apache::lonxml::debug=$env{'user.debug'};
           
     $Apache::lonxml::debug=$ENV{'user.debug'};      &Apache::loncommon::content_type($request,'text/html');
       
     if ($ENV{'browser.mathml'}) {  
  &Apache::loncommon::content_type($request,'text/xml');  
     } else {  
  &Apache::loncommon::content_type($request,'text/html');  
     }  
     &Apache::loncommon::no_cache($request);      &Apache::loncommon::no_cache($request);
       if ($env{'request.state'} eq 'published') {
    $request->set_last_modified(&Apache::lonnet::metadata($request->uri,
         'lastrevisiondate'));
       }
       # Embedded Flash movies from Camtasia served from https will not display in IE
       #   if XML config file has expired from cache.    
       if ($ENV{'SERVER_PORT'} == 443) {
           if ($request->uri =~ /\.xml$/) {
               my ($httpbrowser,$clientbrowser) =
                   &Apache::loncommon::decode_user_agent($request);
               if ($clientbrowser =~ /^explorer$/i) {
                   delete $request->headers_out->{'Cache-control'};
                   delete $request->headers_out->{'Pragma'};
                   my $expiration = time + 60;
                   my $date=strftime("%a, %d %b %Y %H:%M:%S GMT",gmtime($expiration));
                   $request->headers_out->set("Expires" => $date);
               }
           }
       }
     $request->send_http_header;      $request->send_http_header;
           
     return OK if $request->header_only;      return OK if $request->header_only;
   
   
     my $file=&Apache::lonnet::filelocation("",$request->uri);      my $file=&Apache::lonnet::filelocation("",$request->uri);
     my $filetype;      my ($filetype,$breadcrumbtext);
     if ($file =~ /\.sty$/) {      if ($file =~ /\.(sty|css|js|txt|tex)$/) {
  $filetype='sty';   $filetype=$1;
     } else {      } else {
  $filetype='html';   $filetype='html';
     }      }
       unless ($env{'request.uri'}) {
           $env{'request.uri'}=$request->uri;
           &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
                                                   ['todocs']);
       }
       my ($cdom,$cnum);
       if ($env{'request.course.id'}) {
           $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
           $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
           if ($filetype eq 'html') {
               if ($request->uri =~ m{^\Q/uploaded/$cdom/$cnum/portfolio/syllabus/\E.+$}) {
                   if (&Apache::lonnet::allowed('mdc',$env{'request.course.id'})) {
                       &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
                                                               ['editmode']);
                   }
               }
           }
       }
       if ($filetype eq 'sty') {
           $breadcrumbtext = 'Style File Editor';
       } elsif ($filetype eq 'js') {
           $breadcrumbtext = 'Javascript Editor';
       } elsif ($filetype eq 'css') {
           $breadcrumbtext = 'CSS Editor';
       } elsif ($filetype eq 'txt') {
           $breadcrumbtext = 'Text Editor';
       } elsif ($filetype eq 'tex') {
           $breadcrumbtext = 'TeX Editor';
       } else {
           $breadcrumbtext = 'HTML Editor';
       }
   
 #  #
 # Edit action? Save file.  # Edit action? Save file.
 #  #
     unless ($ENV{'request.state'} eq 'published') {      if (!($env{'request.state'} eq 'published')) {
  if (($ENV{'form.savethisfile'}) || ($ENV{'form.attemptclean'})) {   if ($env{'form.savethisfile'} || $env{'form.viewmode'} || $env{'form.Undo'}) {
     if (&storefile($file,$ENV{'form.filecont'})) {      my $html_file=&Apache::lonnet::getfile($file);
  &Apache::lonxml::info("<font COLOR=\"#0000FF\">".      my $error = &Apache::lonhomework::handle_save_or_undo($request, \$html_file, \$env{'form.filecont'});
       &mt('Updated').": ".              if ($env{'form.savethisfile'}) {
       &Apache::lonlocal::locallocaltime(time).                  $env{'form.editmode'}='Edit'; #force edit mode
       " </font>");              }
     }   
  }   }
     }      }
       my $inhibit_menu;
     my %mystyle;      my %mystyle;
     my $result = '';      my $result = '';
     my $filecontents=&Apache::lonnet::getfile($file);      my $filecontents=&Apache::lonnet::getfile($file);
     if ($filecontents eq -1) {      if ($filecontents eq -1) {
  my $bodytag=&Apache::loncommon::bodytag('File Error');   my $start_page=&Apache::loncommon::start_page('File Error');
  my $fnf=&mt('File not found');   my $end_page=&Apache::loncommon::end_page();
           my $errormsg='<p class="LC_error">'
                       .&mt('File not found: [_1]'
                           ,'<span class="LC_filename">'.$file.'</span>')
                       .'</p>';
  $result=(<<ENDNOTFOUND);   $result=(<<ENDNOTFOUND);
 <html>  $start_page
 <head>  $errormsg
 <title>$fnf</title>  $end_page
 </head>  
 $bodytag  
 <b>$fnf: $file</b>  
 </body>  
 </html>  
 ENDNOTFOUND  ENDNOTFOUND
     $filecontents='';          $filecontents='';
  if ($ENV{'request.state'} ne 'published') {   if ($env{'request.state'} ne 'published') {
     if ($filetype eq 'sty') {      if ($filetype eq 'sty') {
  $filecontents=&createnewsty();   $filecontents=&createnewsty();
     } else {              } elsif ($filetype eq 'js') {
                   $filecontents=&createnewjs();
               } elsif ($filetype ne 'css' && $filetype ne 'txt' && $filetype ne 'tex') {
  $filecontents=&createnewhtml();   $filecontents=&createnewhtml();
     }      }
     $ENV{'form.editmode'}='Edit'; #force edit mode      $env{'form.editmode'}='Edit'; #force edit mode
  }   }
     } else {      } else {
  unless ($ENV{'request.state'} eq 'published') {   unless ($env{'request.state'} eq 'published') {
     if ($ENV{'form.attemptclean'}) {      if ($filecontents=~/BEGIN LON-CAPA Internal/) {
  $filecontents=&htmlclean($filecontents,1);   &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.'));
     }      }
 #  #
 # we are in construction space, see if edit mode forced  # we are in construction space, see if edit mode forced
             &Apache::loncommon::get_unprocessed_cgi              &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
                           ($ENV{'QUERY_STRING'},['editmode']);      ['editmode']);
  }  
  if (!$ENV{'form.editmode'} || $ENV{'form.viewmode'}) {  
     $result = &Apache::lonxml::xmlparse($request,$target,$filecontents,  
  '',%mystyle);  
  }   }
    if (!$env{'form.editmode'} || $env{'form.viewmode'} || $env{'form.discardview'}) {
               if ($filetype eq 'html' || $filetype eq 'sty') {
           &Apache::structuretags::reset_problem_globals();
           $result = &Apache::lonxml::xmlparse($request,$target,
                                                       $filecontents,'',%mystyle);
       # .html files may contain <problem> or <Task> need to clean
       # up if it did
           &Apache::structuretags::reset_problem_globals();
           &Apache::lonhomework::finished_parsing();
               } elsif ($filetype eq 'tex') {
                   $result = &Apache::lontexconvert::converted(\$filecontents,
                                 $env{'form.texengine'});
                   if ($env{'form.return_only_error_and_warning_counts'}) {
                       $result = "$errorcount:$warningcount";
                   }
               } else {
                   $result = $filecontents;
               }
       &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
       ['rawmode']);
       if ($env{'form.rawmode'}) { $result = $filecontents; }
               if (($env{'request.state'} eq 'construct') &&
                   (($filetype eq 'css') || ($filetype eq 'js')) && ($ENV{'HTTP_REFERER'})) {
                   if ($ENV{'HTTP_REFERER'} =~ m{^https?\://[^\/]+/priv/$LONCAPA::match_domain/$LONCAPA::match_username/[^\?]+\.(x?html?|swf)(|\?)[^\?]*$}) {
                       $inhibit_menu = 1;
                   }
               }
               if (($filetype ne 'html') && 
                   (!$env{'form.return_only_error_and_warning_counts'}) &&
                   (!$inhibit_menu)) {
                   my $nochgview = 1;
                   my $controls = '';
                       if ($env{'request.state'} eq 'construct') {
                           $controls = &Apache::loncommon::head_subbox(
                                           &Apache::loncommon::CSTR_pageheader()
                                          .&Apache::londefdef::edit_controls($nochgview));
                       }
                   if ($filetype ne 'sty' && $filetype ne 'tex') {
                       $result =~ s/</&lt;/g;
                       $result =~ s/>/&gt;/g;
                       $result = '<table class="LC_sty_begin">'.
                                 '<tr><td><b><pre>'.$result.
                                 '</pre></b></td></tr></table>';
                   }
                   my $brcrum;
                   if ($env{'request.state'} eq 'construct') {
                       $brcrum = [{'href' => &Apache::loncommon::authorspace($request->uri),
                                   'text' => 'Authoring Space'},
                                  {'href' => '',
                                   'text' => $breadcrumbtext}];
                   } else {
                       $brcrum = ''; # FIXME: Where are we?
                   }
                   my %options = ('bread_crumbs' => $brcrum,
                                  'bgcolor'      => '#FFFFFF');
                   $result =
                       &Apache::loncommon::start_page(undef,undef,\%options)
                      .$controls
                      .$result
                      .&Apache::loncommon::end_page();
               }
           }
     }      }
       
 #  #
 # Edit action? Insert editing commands  # Edit action? Insert editing commands
 #  #
     unless ($ENV{'request.state'} eq 'published') {      unless (($env{'request.state'} eq 'published') || ($inhibit_menu)) {
  if ($ENV{'form.editmode'} && (!($ENV{'form.viewmode'}))) {   if ($env{'form.editmode'} && (!($env{'form.viewmode'})) && (!($env{'form.discardview'})))
     my $displayfile=$request->uri;   {
     $displayfile=~s/^\/[^\/]*//;              my ($displayfile,$url,$symb,$itemtitle,$action);
     $result='<html><body bgcolor="#FFFFFF">'.      $displayfile=$request->uri;
  &Apache::lonxml::message_location().'<h3>'.              if ($request->uri =~ m{^/uploaded/}) {
  $displayfile.                  if ($env{'request.course.id'}) {
  '</h3></body></html>';                      if ($request->uri =~ m{^\Q/uploaded/$cdom/$cnum/supplemental/\E}) {
     $result=&inserteditinfo($result,$filecontents,$filetype);                          &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
  }                                                                  ['folderpath','title']);
                       } elsif ($request->uri =~ m{^\Q/uploaded/$cdom/$cnum/portfolio/syllabus/\E(.+)$}) {
                           my $filename = $1;
                           if ($1 eq 'loncapa.html') {
                               $displayfile = &mt('Syllabus (minimal template)');
                               $action = $request->uri.'?forceedit=1';
                           } else {
                               $displayfile = &mt('Syllabus file: [_1]',$1);
                           }
                           $itemtitle = &mt('Syllabus');
                       }
                   }
                   unless ($itemtitle) {
                       ($symb,$itemtitle,$displayfile) = 
                           &get_courseupload_hierarchy($request->uri,
                                                       $env{'form.folderpath'},
                                                       $env{'form.title'});
                   }
               } else {
           $displayfile=~s/^\/[^\/]*//;
               }
   
       my ($edit_info, $add_to_onload, $add_to_onresize)=
    &inserteditinfo($filecontents,$filetype,$displayfile,$symb,
                                   $itemtitle,$env{'form.folderpath'},$request->uri,$action);
   
       my %options = 
    ('add_entries' =>
                      {'onresize'     => $add_to_onresize,
                       'onload'       => $add_to_onload,   });
               my $header;
               if ($env{'request.state'} eq 'construct') {
                   $options{'bread_crumbs'} = [{
                               'href' => &Apache::loncommon::authorspace($request->uri),
                               'text' => 'Authoring Space'},
                              {'href' => '',
                               'text' => $breadcrumbtext}];
                   $header = &Apache::loncommon::head_subbox(
                                 &Apache::loncommon::CSTR_pageheader());
               }
       my $js =
    &Apache::edit::js_change_detection().
    &Apache::loncommon::resize_textarea_js();
       my $start_page = &Apache::loncommon::start_page(undef,$js,
       \%options);
               $result = $start_page
                        .$header
                        .&Apache::lonxml::message_location()
                        .$edit_info
                        .&Apache::loncommon::end_page();
           }
     }      }
     if ($filetype eq 'html') { writeallows($request->uri); }      if ($filetype eq 'html') { &writeallows($request->uri); }
   
       
     &Apache::lonxml::add_messages(\$result);      &Apache::lonxml::add_messages(\$result);
     $request->print($result);      $request->print($result);
           
Line 1310  ENDNOTFOUND Line 2039  ENDNOTFOUND
   
 sub display_title {  sub display_title {
     my $result;      my $result;
     if ($ENV{'request.state'} eq 'construct') {      if ($env{'request.state'} eq 'construct') {
  my $title=&Apache::lonnet::gettitle();   my $title=&Apache::lonnet::gettitle();
  if (!defined($title) || $title eq '') {   if (!defined($title) || $title eq '') {
     $title = $ENV{'request.filename'};      $title = $env{'request.filename'};
     $title = substr($title, rindex($title, '/') + 1);      $title = substr($title, rindex($title, '/') + 1);
  }   }
  $result = "<script type='text/javascript'>top.document.title = '$title - LON-CAPA Construction Space';</script>";          $result = "<script type='text/javascript'>top.document.title = '$title - LON-CAPA "
                     .&mt('Authoring Space')."';</script>";
     }      }
     return $result;      return $result;
 }  }
   
   sub get_courseupload_hierarchy {
       my ($url,$folderpath,$title) = @_;
       my ($symb,$itemtitle,$displaypath);
       if ($env{'request.course.id'}) {
           if ($folderpath =~ /^supplemental/) {
               my @folders = split(/\&/,$folderpath);
               my @pathitems;
               while (@folders) {
                   my $folder=shift(@folders);
                   my $foldername=shift(@folders);
                   $foldername =~ s/\:(\d*)\:(\w*)\:(\w*):(\d*)\:?(\d*)$//;
                   push(@pathitems,&unescape($foldername));
               }
               if ($title) {
                   push(@pathitems,&unescape($title));
               }
               $displaypath = join(' &raquo; ',@pathitems);
           } else {
               $symb = &Apache::lonnet::symbread($url);
               my ($map,$id,$res)=&Apache::lonnet::decode_symb($symb);
               my $navmap=Apache::lonnavmaps::navmap->new;
               if (ref($navmap)) {
                   my $res = $navmap->getBySymb($symb);
                   if (ref($res)) {
                       my @pathitems =
                           &Apache::loncommon::get_folder_hierarchy($navmap,$map,1);
                       $itemtitle = $res->compTitle();
                       push(@pathitems,$itemtitle);
                       $displaypath = join(' &raquo; ',@pathitems);
                   }
               }
           }
       }
       return ($symb,$itemtitle,$displaypath);
   }
   
 sub debug {  sub debug {
     if ($Apache::lonxml::debug eq "1") {      if ($Apache::lonxml::debug eq "1") {
  $|=1;   $|=1;
  my $request=$Apache::lonxml::request;   my $request=$Apache::lonxml::request;
  if (!$request) { $request=Apache->request; }   if (!$request) {
       eval { $request=Apache->request; };
    }
    if (!$request) {
       eval { $request=Apache2::RequestUtil->request; };
    }
  $request->print('<font size="-2"><pre>DEBUG:'.&HTML::Entities::encode($_[0],'<>&"')."</pre></font>\n");   $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 
            $Apache::lonnet::perlvar{'lonDocRoot'}.'/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 {  sub error {
   $errorcount++;      my @errors = @_;
   my $request=$Apache::lonxml::request;  
   if (!$request) { $request=Apache->request; }      $errorcount++;
   if (($Apache::lonxml::debug eq 1) || ($ENV{'request.state'} eq 'construct') ) {  
     # If printing in construction space, put the error inside <pre></pre>      $Apache::lonxml::internal_error=1;
       push(@Apache::lonxml::error_messages,  
    $Apache::lonxml::warnings_error_header.      if (defined($Apache::inputtags::part)) {
    "<b>ERROR:</b>".join("<br />\n",@_)."<br />\n");   if ( @Apache::inputtags::response ) {
       $Apache::lonxml::warnings_error_header='';      push(@errors,
   } else {   &mt("This error occurred while processing response [_1] in part [_2]",
       push(@Apache::lonxml::error_messages,       $Apache::inputtags::response[-1],
    "<b>An Error occured while processing this resource. The instructor has been notified.</b> <br />");       $Apache::inputtags::part));
     #notify author   } else {
     &Apache::lonmsg::author_res_msg($ENV{'request.filename'},join('<br />',@_));      push(@errors,
     #notify course   &mt("This error occurred while processing part [_1]",
     if ( $ENV{'request.course.id'} ) {       $Apache::inputtags::part));
       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(/:/, $_);      if ( &show_error_warn_msg() ) {
  &Apache::lonmsg::user_normal_msg($user,$domain,   # If printing in construction space, put the error inside <pre></pre>
         "Error [$declutter]",join('<br />',@_));   push(@Apache::lonxml::error_messages,
       }       $Apache::lonxml::warnings_error_header
                .'<div class="LC_error">'
                .'<b>'.&mt('ERROR:').' </b>'.join("<br />\n",@errors)
                ."</div>\n");
    $Apache::lonxml::warnings_error_header='';
       } else {
    my $errormsg;
    my ($symb)=&Apache::lonnet::symbread();
    if ( !$symb ) {
       #public or browsers
       $errormsg=&mt("An error occurred while processing this resource. The author has been notified.");
    }
    my $host=$Apache::lonnet::perlvar{'lonHostID'};
    push(@errors,
           &mt("The error occurred on host [_1]",
                "<tt>$host</tt>"));
   
    my $msg = join('<br />', @errors);
   
    #notify author
    &Apache::lonmsg::author_res_msg($env{'request.filename'},$msg);
    #notify course
    if ( $symb && $env{'request.course.id'} ) {
       my $cnum=$env{'course.'.$env{'request.course.id'}.'.num'};
       my $cdom=$env{'course.'.$env{'request.course.id'}.'.domain'};
       my (undef,%users)=&Apache::lonmsg::decide_receiver(undef,0,1,1,1);
       my $declutter=&Apache::lonnet::declutter($env{'request.filename'});
               my $baseurl = &Apache::lonnet::clutter($declutter);
       my @userlist;
       foreach (keys(%users)) {
    my ($user,$domain) = split(/:/, $_);
    push(@userlist,"$user:$domain");
    my $key=$declutter.'_'.$user.'_'.$domain;
    my %lastnotified=&Apache::lonnet::get('nohist_xmlerrornotifications',
         [$key],
         $cdom,$cnum);
    my $now=time;
    if ($now-$lastnotified{$key}>86400) {
                       my $title = &Apache::lonnet::gettitle($symb);
                       my $sentmessage;
       &Apache::lonmsg::user_normal_msg($user,$domain,
           "Error [$title]",$msg,'',$baseurl,'','',
                           \$sentmessage,$symb,$title,1);
       &Apache::lonnet::put('nohist_xmlerrornotifications',
    {$key => $now},
    $cdom,$cnum);
    }
       }
       if ($env{'request.role.adv'}) {
    $errormsg=&mt("An error occurred while processing this resource. The course personnel ([_1]) and the author have been notified.",join(', ',@userlist));
       } else {
    $errormsg=&mt("An error occurred while processing this resource. The instructor has been notified.");
       }
    }
    push(@Apache::lonxml::error_messages,"<span class=\"LC_warning\">$errormsg</span><br />");
     }      }
   }  
 }  }
   
 sub warning {  sub warning {
     $warningcount++;      $warningcount++;
       
     if ($ENV{'form.grade_target'} ne 'tex') {      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,      push(@Apache::lonxml::warning_messages,
  $Apache::lonxml::warnings_error_header.   $Apache::lonxml::warnings_error_header
  "<b>W</b>ARNING<b>:</b>".join('<br />',@_)."<br />\n");                  .'<div class="LC_warning">'
                   .&mt('[_1]W[_2]ARNING','<b>','</b>')."<b>:</b> ".join('<br />',@_)
                   ."</div>\n"
                   );
     $Apache::lonxml::warnings_error_header='';      $Apache::lonxml::warnings_error_header='';
  }   }
     }      }
 }  }
   
 sub info {  sub info {
     if ($ENV{'form.grade_target'} ne 'tex'       if ($env{'form.grade_target'} ne 'tex' 
  && $ENV{'request.state'} eq 'construct') {   && $env{'request.state'} eq 'construct') {
  push(@Apache::lonxml::info_messages,join('<br />',@_)."<br />\n");   push(@Apache::lonxml::info_messages,join('<br />',@_)."<br />\n");
     }      }
 }  }
Line 1399  sub add_messages { Line 2237  sub add_messages {
 }  }
   
 sub get_param {  sub get_param {
     my ($param,$parstack,$safeeval,$context,$case_insensitive) = @_;      my ($param,$parstack,$safeeval,$context,$case_insensitive, $noelide) = @_;
     if ( ! $context ) { $context = -1; }      if ( ! $context ) { $context = -1; }
     my $args ='';      my $args ='';
     if ( $#$parstack > (-2-$context) ) { $args=$$parstack[$context]; }      if ( $#$parstack > (-2-$context) ) { $args=$$parstack[$context]; }
     if ( ! $Apache::lonxml::usestyle ) {      if ( ! $Apache::lonxml::usestyle ) {
  $args=$Apache::lonxml::style_values.$args;   $args=$Apache::lonxml::style_values.$args;
     }      }
   
       if ($noelide) {
           $args =~ s/'\$/'\\\$/g;
       }
   
     if ( ! $args ) { return undef; }      if ( ! $args ) { return undef; }
     if ( $case_insensitive ) {      if ( $case_insensitive ) {
  if ($args =~ s/(my \$)(\Q$param\E)(=\")/$1.lc($2).$3/ei) {   if ($args =~ s/(my (?:.*))(\$\Q$param\E[,\)])/$1.lc($2)/ei) {
     return &Apache::run::run("{$args;".'return $'.$param.'}',      return &Apache::run::run("{$args;".'return $'.$param.'}',
                                      $safeeval); #'                                       $safeeval); #'
  } else {   } else {
     return undef;      return undef;
  }   }
     } else {      } else {
  if ( $args =~ /my \$\Q$param\E=\"/ ) {   if ( $args =~ /my .*\$\Q$param\E[,\)]/ ) {
     return &Apache::run::run("{$args;".'return $'.$param.'}',      return &Apache::run::run("{$args;".'return $'.$param.'}',
                                      $safeeval); #'                                       $safeeval); #'
  } else {   } else {
Line 1434  sub get_param_var { Line 2277  sub get_param_var {
   }    }
   &Apache::lonxml::debug("Args are $args param is $param");    &Apache::lonxml::debug("Args are $args param is $param");
   if ($case_insensitive) {    if ($case_insensitive) {
       if (! ($args=~s/(my \$)(\Q$param\E)(=\")/$1.lc($2).$3/ei)) {        if (! ($args=~s/(my (?:.*))(\$\Q$param\E[,\)])/$1.lc($2)/ei)) {
   return undef;    return undef;
       }        }
   } elsif ( $args !~ /my \$\Q$param\E=\"/ ) { return undef; }    } elsif ( $args !~ /my .*\$\Q$param\E[,\)]/ ) { return undef; }
   my $value=&Apache::run::run("{$args;".'return $'.$param.'}',$safeeval); #'    my $value=&Apache::run::run("{$args;".'return $'.$param.'}',$safeeval); #'
   &Apache::lonxml::debug("first run is $value");    &Apache::lonxml::debug("first run is $value");
   if ($value =~ /^[\$\@\%]\w+$/) {    if ($value =~ /^[\$\@\%][a-zA-Z_]\w*$/) {
       &Apache::lonxml::debug("doing second");        &Apache::lonxml::debug("doing second");
       my @result=&Apache::run::run("return $value",$safeeval,1);        my @result=&Apache::run::run("return $value",$safeeval,1);
       if (!defined($result[0])) {        if (!defined($result[0])) {
Line 1453  sub get_param_var { Line 2296  sub get_param_var {
   }    }
 }  }
   
 sub register_insert {  sub register_insert_xml {
   my @data = split /\n/, &Apache::lonnet::getfile('/home/httpd/lonTabs/insertlist.tab');      my $parser = HTML::LCParser->new($Apache::lonnet::perlvar{'lonTabDir'}
   my $i;       .'/insertlist.xml');
   my $tagnum=0;      my ($tagnum,$in_help)=(0,0);
   my @order;      my @alltags;
   for ($i=0;$i < $#data; $i++) {      my $tag;
     my $line = $data[$i];      while (my $token = $parser->get_token()) {
     if ( $line =~ /^\#/ || $line =~ /^\s*\n/) { next; }   if ($token->[0] eq 'S') {
     if ( $line =~ /TABLE/ ) { last; }      my $key;
     my ($tag,$descrip,$color,$function,$show,$helpfile,$helpdesc) = split(/,/, $line);      if ($token->[1] eq 'tag') {
     if ($tag) {   $tag = $token->[2]{'name'};
       $insertlist{"$tagnum.tag"} = $tag;                  if (defined($tag)) {
       $insertlist{"$tagnum.description"} = $descrip;      $insertlist{$tagnum.'.tag'} = $tag;
       $insertlist{"$tagnum.color"} = $color;      $insertlist{$tag.'.num'}   = $tagnum;
       $insertlist{"$tagnum.function"} = $function;      push(@alltags,$tag);
       if (!defined($show)) { $show='yes'; }                  }
       $insertlist{"$tagnum.show"}= $show;      } elsif ($in_help && $token->[1] eq 'file') {
       $insertlist{"$tagnum.helpfile"} = $helpfile;   $key = $tag.'.helpfile';
       $insertlist{"$tagnum.helpdesc"} = $helpdesc;      } elsif ($in_help && $token->[1] eq 'description') {
       $insertlist{"$tag.num"}=$tagnum;   $key = $tag.'.helpdesc';
       $tagnum++;      } elsif ($token->[1] eq 'description' ||
        $token->[1] eq 'color'       ||
        $token->[1] eq 'show'          ) {
    $key = $tag.'.'.$token->[1];
       } elsif ($token->[1] eq 'insert_sub') {
    $key = $tag.'.function';
       } elsif ($token->[1] eq 'help') {
    $in_help=1;
       } elsif ($token->[1] eq 'allow') {
    $key = $tag.'.allow';
       }
       if (defined($key)) {
    $insertlist{$key} = $parser->get_text();
    $insertlist{$key} =~ s/(^\s*|\s*$ )//gx;
       }
    } elsif ($token->[0] eq 'E') {
       if      ($token->[1] eq 'tag') {
    undef($tag);
    $tagnum++;
       } elsif ($token->[1] eq 'help') {
    undef($in_help);
       }
    }
     }      }
   }      
   $i++; #skipping TABLE line      # parse the allows and ignore tags set to <show>no</show>
   $tagnum = 0;      foreach my $tag (@alltags) {
   for (;$i < $#data;$i++) {          next if (!exists($insertlist{$tag.'.allow'}));
     my $line = $data[$i];   my $allow =  $insertlist{$tag.'.allow'};
     my ($mnemonic,@which) = split(/ +/,$line);          foreach my $element (split(',',$allow)) {
     my $tag = $insertlist{"$tagnum.tag"};      $element =~ s/(^\s*|\s*$ )//gx;
     for (my $j=0;$j <=$#which;$j++) {      if (!exists($insertlist{$element.'.show'})
       if ( $which[$j] eq 'Y' ) {                  || $insertlist{$element.'.show'} ne 'no') {
  if ($insertlist{"$j.show"} ne 'no') {   push(@{ $insertlist{$tag.'.which'} },$element);
   push(@{ $insertlist{"$tag.which"} },$j);      }
  }   }
       }  
     }      }
     $tagnum++;  }
   }  
   sub register_insert {
       return &register_insert_xml(@_);
   #    &dump_insertlist('2');
   }
   
   sub dump_insertlist {
       my ($ext) = @_;
       open(XML,">/tmp/insertlist.xml.$ext");
       print XML ("<insertlist>");
       my $i=0;
   
       while (exists($insertlist{"$i.tag"})) {
    my $tag = $insertlist{"$i.tag"};
    print XML ("
   \t<tag name=\"$tag\">");
    if (defined($insertlist{"$tag.description"})) {
       print XML ("
   \t\t<description>".$insertlist{"$tag.description"}."</description>");
    }
    if (defined($insertlist{"$tag.color"})) {
       print XML ("
   \t\t<color>".$insertlist{"$tag.color"}."</color>");
    }
    if (defined($insertlist{"$tag.function"})) {
       print XML ("
   \t\t<insert_sub>".$insertlist{"$tag.function"}."</insert_sub>");
    }
    if (defined($insertlist{"$tag.show"})
       && $insertlist{"$tag.show"} ne 'yes') {
       print XML ("
   \t\t<show>".$insertlist{"$tag.show"}."</show>");
    }
    if (defined($insertlist{"$tag.helpfile"})) {
       print XML ("
   \t\t<help>
   \t\t\t<file>".$insertlist{"$tag.helpfile"}."</file>");
       if ($insertlist{"$tag.helpdesc"} ne '') {
    print XML ("
   \t\t\t<description>".$insertlist{"$tag.helpdesc"}."</description>");
       }
       print XML ("
   \t\t</help>");
    }
    if (defined($insertlist{"$tag.which"})) {
       print XML ("
   \t\t<allow>".join(',',sort(@{ $insertlist{"$tag.which"} }))."</allow>");
    }
    print XML ("
   \t</tag>");
    $i++;
       }
       print XML ("\n</insertlist>\n");
       close(XML);
 }  }
   
 sub description {  sub description {
   my ($token)=@_;      my ($token)=@_;
   my $tagnum;      my $tag = &get_tag($token);
   my $tag=$token->[1];      return $insertlist{$tag.'.description'};
   foreach my $namespace (reverse @Apache::lonxml::namespace) {  
     my $testtag=$namespace.'::'.$tag;  
     $tagnum=$insertlist{"$testtag.num"};  
     if (defined($tagnum)) { last; }  
   }  
   if (!defined ($tagnum)) { $tagnum=$Apache::lonxml::insertlist{"$tag.num"}; }  
   return $insertlist{$tagnum.'.description'};  
 }  }
   
 # Returns a list containing the help file, and the description  # Returns a list containing the help file, and the description
 sub helpinfo {  sub helpinfo {
   my ($token)=@_;      my ($token)=@_;
   my $tagnum;      my $tag = &get_tag($token);
   my $tag=$token->[1];      return ($insertlist{$tag.'.helpfile'}, &mt($insertlist{$tag.'.helpdesc'}));
   foreach my $namespace (reverse @Apache::lonxml::namespace) {  
     my $testtag=$namespace.'::'.$tag;  
     $tagnum=$insertlist{"$testtag.num"};  
     if (defined($tagnum)) { last; }  
   }  
   if (!defined ($tagnum)) { $tagnum=$Apache::lonxml::insertlist{"$tag.num"}; }  
   return ($insertlist{$tagnum.'.helpfile'}, $insertlist{$tagnum.'.helpdesc'});  
 }  }
   
 # ----------------------------------------------------------------- whichuser  sub get_tag {
 # returns a list of $symb, $courseid, $domain, $name that is correct for      my ($token)=@_;
 # calls to lonnet functions for this setup.      my $tagnum;
 # - looks for form.grade_ parameters      my $tag=$token->[1];
 sub whichuser {      foreach my $namespace (reverse(@Apache::lonxml::namespace)) {
   my ($passedsymb)=@_;   my $testtag = $namespace.'::'.$tag;
   my ($symb,$courseid,$domain,$name,$publicuser);   $tagnum = $insertlist{"$testtag.num"};
   if (defined($ENV{'form.grade_symb'})) {   last if (defined($tagnum));
     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 (!defined($tagnum)) {
       if (!$passedsymb) {   $tagnum = $Apache::lonxml::insertlist{"$tag.num"};
           $symb=&Apache::lonnet::symbread();      }
       } else {      return $insertlist{"$tagnum.tag"};
           $symb=$passedsymb;  }
       }  
       $courseid=$ENV{'request.course.id'};  ############################################################
       $domain=$ENV{'user.domain'};  #                                           PDF-FORM-METHODS
       $name=$ENV{'user.name'};  
       if ($name eq 'public' && $domain eq 'public') {  =pod
   if (!defined($ENV{'form.username'})) {  
       $ENV{'form.username'}.=time.rand(10000000);  =item &print_pdf_radiobutton(fieldname, value)
   }  
   $name.=$ENV{'form.username'};  Returns a latexline to generate a PDF-Form-Radiobutton.
       }  Note: Radiobuttons with equal names are automaticly grouped 
   }        in a selection-group.
   return ($symb,$courseid,$domain,$name,$publicuser);  
   $fieldname: PDF internalname of the radiobutton(group)
   $value:     Value of radiobutton
   
   =cut
   sub print_pdf_radiobutton {
       my ($fieldname, $value) = @_;
       return '\radioButton[\symbolchoice{circle}]{'
              .$fieldname.'}{10bp}{10bp}{'.$value.'}';
   }
   
   
   =pod
   
   =item &print_pdf_start_combobox(fieldname)
   
   Starts a latexline to generate a PDF-Form-Combobox with text.
   
   $fieldname: PDF internal name of the Combobox
   
   =cut
   sub print_pdf_start_combobox {
       my $result;
       my ($fieldName) = @_;
       $result .= '\begin{tabularx}{\textwidth}{p{2.5cm}X}'."\n";
       $result .= '\comboBox[]{'.$fieldName.'}{2.3cm}{14bp}{'; # 
   
       return $result;
   }
   
   
   =pod
   
   =item &print_pdf_add_combobox_option(options)
   
   Generates a latexline to add Options to a PDF-Form-ComboBox.
   
   $option: PDF internal name of the Combobox-Option
   
   =cut
   sub print_pdf_add_combobox_option {
   
       my $result;
       my ($option) = @_;  
   
       $result .= '('.$option.')';
       
       return $result;
   }
   
   
   =pod
   
   =item &print_pdf_end_combobox(text) {
   
   Returns latexcode to end a PDF-Form-Combobox with text.
   
   =cut
   sub print_pdf_end_combobox {
       my $result;
       my ($text) = @_;
   
       $result .= '}&'.$text."\\\\\n";
       $result .= '\end{tabularx}' . "\n";
       $result .= '\hspace{2mm}' . "\n";
       return $result;
   }
   
   
   =pod
   
   =item &print_pdf_hiddenField(fieldname, user, domain)
   
   Returns a latexline to generate a PDF-Form-hiddenField with userdata.
   
   $fieldname label for hiddentextfield
   $user:    name of user
   $domain:  domain of user
   
   =cut
   sub print_pdf_hiddenfield {
       my $result;
       my ($fieldname, $user, $domain) = @_;
   
       $result .= '\textField [\F{\FHidden}\F{-\FPrint}\V{'.$domain.'&'.$user.'}]{'.$fieldname.'}{0in}{0in}'."\n";
   
       return $result;
 }  }
   
 1;  1;
 __END__  __END__
   
   

Removed from v.1.333  
changed lines
  Added in v.1.531.2.20


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>