Annotation of loncom/xml/lonxml.pm, revision 1.543

1.2       sakharuk    1: # The LearningOnline Network with CAPA
1.3       sakharuk    2: # XML Parser Module 
1.2       sakharuk    3: #
1.543   ! raeburn     4: # $Id: lonxml.pm,v 1.542 2013/07/15 16:13:36 bisitz Exp $
1.139     www         5: #
                      6: # Copyright Michigan State University Board of Trustees
                      7: #
                      8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
                      9: #
                     10: # LON-CAPA is free software; you can redistribute it and/or modify
                     11: # it under the terms of the GNU General Public License as published by
                     12: # the Free Software Foundation; either version 2 of the License, or
                     13: # (at your option) any later version.
                     14: #
                     15: # LON-CAPA is distributed in the hope that it will be useful,
                     16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
                     17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     18: # GNU General Public License for more details.
                     19: #
                     20: # You should have received a copy of the GNU General Public License
                     21: # along with LON-CAPA; if not, write to the Free Software
                     22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     23: #
                     24: # /home/httpd/html/adm/gpl.txt
                     25: #
                     26: # http://www.lon-capa.org/
                     27: #
                     28: # Copyright for TtHfunc and TtMfunc by Ian Hutchinson. 
                     29: # TtHfunc and TtMfunc (the "Code") may be compiled and linked into 
                     30: # binary executable programs or libraries distributed by the 
                     31: # Michigan State University (the "Licensee"), but any binaries so 
                     32: # distributed are hereby licensed only for use in the context
                     33: # of a program or computational system for which the Licensee is the 
                     34: # primary author or distributor, and which performs substantial 
                     35: # additional tasks beyond the translation of (La)TeX into HTML.
                     36: # The C source of the Code may not be distributed by the Licensee
                     37: # to any other parties under any circumstances.
                     38: #
1.316     albertel   39: 
1.489     jms        40: =pod
                     41: 
                     42: =head1 NAME
                     43: 
                     44: Apache::lonxml
                     45: 
                     46: =head1 SYNOPSIS
                     47: 
                     48: XML Parsing Module
                     49: 
                     50: This is part of the LearningOnline Network with CAPA project
                     51: described at http://www.lon-capa.org.
                     52: 
                     53: 
                     54: =head1 SUBROUTINES
                     55: 
                     56: =cut
                     57: 
                     58: 
1.2       sakharuk   59: 
1.4       albertel   60: package Apache::lonxml; 
1.33      www        61: use vars 
1.410     albertel   62: qw(@pwd @outputstack $redirection $import @extlinks $metamode $evaluate %insertlist @namespace $errorcount $warningcount);
1.1       sakharuk   63: use strict;
1.444     albertel   64: use LONCAPA;
1.167     albertel   65: use HTML::LCParser();
1.161     albertel   66: use HTML::TreeBuilder();
                     67: use HTML::Entities();
                     68: use Safe();
                     69: use Safe::Hole();
                     70: use Math::Cephes();
                     71: use Math::Random();
                     72: use Opcode();
1.271     www        73: use POSIX qw(strftime);
1.339     albertel   74: use Time::HiRes qw( gettimeofday tv_interval );
1.393     albertel   75: use Symbol();
1.266     bowersj2   76: 
1.72      albertel   77: sub register {
1.141     albertel   78:   my ($space,@taglist) = @_;
                     79:   foreach my $temptag (@taglist) {
                     80:     push(@{ $Apache::lonxml::alltags{$temptag} },$space);
1.72      albertel   81:   }
                     82: }
                     83: 
1.141     albertel   84: sub deregister {
                     85:   my ($space,@taglist) = @_;
                     86:   foreach my $temptag (@taglist) {
                     87:     my $tempspace = $Apache::lonxml::alltags{$temptag}[-1];
                     88:     if ($tempspace eq $space) {
                     89:       pop(@{ $Apache::lonxml::alltags{$temptag} });
                     90:     }
                     91:   }
1.142     albertel   92:   #&printalltags();
1.141     albertel   93: }
                     94: 
1.46      www        95: use Apache::Constants qw(:common);
1.161     albertel   96: use Apache::lontexconvert();
                     97: use Apache::style();
                     98: use Apache::run();
                     99: use Apache::londefdef();
                    100: use Apache::scripttag();
1.285     www       101: use Apache::languagetags();
1.161     albertel  102: use Apache::edit();
1.266     bowersj2  103: use Apache::inputtags();
                    104: use Apache::outputtags();
1.372     albertel  105: use Apache::lonnet;
1.161     albertel  106: use Apache::File();
                    107: use Apache::loncommon();
1.198     www       108: use Apache::lonfeedback();
1.200     www       109: use Apache::lonmsg();
1.217     matthew   110: use Apache::loncacc();
1.431     www       111: use Apache::lonmaxima();
1.494     www       112: use Apache::lonr();
1.280     www       113: use Apache::lonlocal;
1.501     raeburn   114: use Apache::lonhtmlcommon();
1.520     www       115: use Apache::functionplotresponse();
1.529     raeburn   116: use Apache::lonnavmaps();
1.79      www       117: 
1.462     foxr      118: #====================================   Main subroutine: xmlparse  
                    119: 
1.72      albertel  120: #debugging control, to turn on debugging modify the correct handler
1.462     foxr      121: 
1.72      albertel  122: $Apache::lonxml::debug=0;
1.206     albertel  123: 
                    124: # keeps count of the number of warnings and errors generated in a parse
                    125: $warningcount=0;
                    126: $errorcount=0;
1.72      albertel  127: 
                    128: #path to the directory containing the file currently being processed
                    129: @pwd=();
                    130: 
                    131: #these two are used for capturing a subset of the output for later processing,
                    132: #don't touch them directly use &startredirection and &endredirection
                    133: @outputstack = ();
                    134: $redirection = 0;
                    135: 
                    136: #controls wheter the <import> tag actually does
                    137: $import = 1;
                    138: @extlinks=();
                    139: 
                    140: # meta mode is a bit weird only some output is to be turned off
                    141: #<output> tag turns metamode off (defined in londefdef.pm)
                    142: $metamode = 0;
                    143: 
                    144: # turns on and of run::evaluate actually derefencing var refs
                    145: $evaluate = 1;
1.7       albertel  146: 
1.74      albertel  147: # data structure for eidt mode, determines what tags can go into what other tags
                    148: %insertlist=();
1.68      www       149: 
1.99      albertel  150: # stores the list of active tag namespaces
1.76      albertel  151: @namespace=();
                    152: 
1.448     albertel  153: # stores all Scrit Vars displays for later showing
                    154: my @script_var_displays=();
                    155: 
1.172     albertel  156: # a pointer the the Apache request object
                    157: $Apache::lonxml::request='';
                    158: 
1.216     sakharuk  159: # a problem number counter, and check on ether it is used
1.237     sakharuk  160: $Apache::lonxml::counter=1;
1.204     albertel  161: $Apache::lonxml::counter_changed=0;
                    162: 
1.462     foxr      163: # Part counter hash.   In analysis mode, the
                    164: # problems can use this to record which parts increment the counter
                    165: # by how much.  The counter subs will maintain this hash via
                    166: # their optional part parameters.  Note that the assumption is that
                    167: # analysis is done in one request and therefore it is not necessary to
                    168: # save this information request-to-request.
                    169: 
                    170: 
                    171: %Apache::lonxml::counters_per_part = ();
                    172: 
1.212     albertel  173: #internal check on whether to look at style defs
                    174: $Apache::lonxml::usestyle=1;
1.260     albertel  175: 
                    176: #locations used to store the parameter string for style substitutions
                    177: $Apache::lonxml::style_values='';
                    178: $Apache::lonxml::style_end_values='';
1.212     albertel  179: 
1.281     albertel  180: #array of ssi calls that need to occur after we are done parsing
                    181: @Apache::lonxml::ssi_info=();
                    182: 
1.282     albertel  183: #should we do the postag variable interpolation
                    184: $Apache::lonxml::post_evaluate=1;
                    185: 
1.295     albertel  186: #a header message to emit in the case of any generated warning or errors
                    187: $Apache::lonxml::warnings_error_header='';
                    188: 
1.396     foxr      189: #  Control whether or not LaTeX symbols should be substituted for their
                    190: #  \ style equivalents...this may be turned off e.g. in an verbatim
                    191: #  environment.
                    192: 
                    193: $Apache::lonxml::substitute_LaTeX_symbols = 1; # Starts out on.
                    194: 
                    195: sub enable_LaTeX_substitutions {
                    196:     $Apache::lonxml::substitute_LaTeX_symbols = 1;
                    197: }
                    198: sub disable_LaTeX_substitutions {
                    199:     $Apache::lonxml::substitute_LaTeX_symbols = 0;
                    200: }
                    201: 
1.68      www       202: sub xmlend {
1.335     sakharuk  203:     my ($target,$parser)=@_;
1.278     www       204:     my $mode='xml';
                    205:     my $status='OPEN';
1.368     albertel  206:     if ($Apache::lonhomework::parsing_a_problem ||
                    207: 	$Apache::lonhomework::parsing_a_task ) {
1.278     www       208: 	$mode='problem';
                    209: 	$status=$Apache::inputtags::status[-1]; 
                    210:     }
1.362     matthew   211:     my $discussion;
1.379     albertel  212:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
                    213: 					   ['LONCAPA_INTERNAL_no_discussion']);
1.528     www       214:     if (
                    215:            (   (!exists($env{'form.LONCAPA_INTERNAL_no_discussion'})) 
                    216:             || ($env{'form.LONCAPA_INTERNAL_no_discussion'} ne 'true')
                    217:            ) 
                    218:         && ($env{'form.inhibitmenu'} ne 'yes')
                    219:        ) {
1.362     matthew   220:         $discussion=&Apache::lonfeedback::list_discussion($mode,$status);
                    221:     }
1.334     sakharuk  222:     if ($target eq 'tex') {
1.335     sakharuk  223: 	$discussion.='<tex>\keephidden{ENDOFPROBLEM}\vskip 0.5mm\noindent\makebox[\textwidth/$number_of_columns][b]{\hrulefill}\end{document}</tex>';
1.334     sakharuk  224: 	&Apache::lonxml::newparser($parser,\$discussion,'');
                    225: 	return '';
                    226:     }
1.405     albertel  227: 
1.407     albertel  228:     return $discussion;
1.119     www       229: }
                    230: 
1.48      albertel  231: sub printalltags {
                    232:   my $temp;
                    233:   foreach $temp (sort keys %Apache::lonxml::alltags) {
1.141     albertel  234:     &Apache::lonxml::debug("$temp -- ".
                    235: 		  join(',',@{ $Apache::lonxml::alltags{$temp} }));
1.48      albertel  236:   }
                    237: }
1.31      sakharuk  238: 
1.3       sakharuk  239: sub xmlparse {
1.172     albertel  240:  my ($request,$target,$content_file_string,$safeinit,%style_for_target) = @_;
1.96      albertel  241: 
1.172     albertel  242:  &setup_globals($request,$target);
1.232     albertel  243:  &Apache::inputtags::initialize_inputtags();
1.370     albertel  244:  &Apache::bridgetask::initialize_bridgetask();
1.232     albertel  245:  &Apache::outputtags::initialize_outputtags();
                    246:  &Apache::edit::initialize_edit();
1.287     albertel  247:  &Apache::londefdef::initialize_londefdef();
1.244     albertel  248: 
1.178     www       249: #
                    250: # do we have a course style file?
                    251: #
                    252: 
1.372     albertel  253:  if ($env{'request.course.id'} && $env{'request.state'} ne 'construct') {
1.178     www       254:      my $bodytext=
1.372     albertel  255: 	 $env{'course.'.$env{'request.course.id'}.'.default_xml_style'};
1.178     www       256:      if ($bodytext) {
1.337     albertel  257: 	 foreach my $file (split(',',$bodytext)) {
                    258: 	     my $location=&Apache::lonnet::filelocation('',$file);
                    259: 	     my $styletext=&Apache::lonnet::getfile($location);
                    260: 	     if ($styletext ne '-1') {
                    261: 		 %style_for_target = (%style_for_target,
                    262: 				      &Apache::style::styleparser($target,$styletext));
                    263: 	     }
                    264: 	 }
                    265:      }
1.449     albertel  266:  } elsif ($env{'construct.style'}
                    267: 	  && ($env{'request.state'} eq 'construct')) {
1.372     albertel  268:      my $location=&Apache::lonnet::filelocation('',$env{'construct.style'});
1.291     sakharuk  269:      my $styletext=&Apache::lonnet::getfile($location);
1.449     albertel  270:      if ($styletext ne '-1') {
                    271: 	 %style_for_target = (%style_for_target,
                    272: 			      &Apache::style::styleparser($target,$styletext));
                    273:      }
1.178     www       274:  }
1.255     sakharuk  275: #&printalltags();
1.16      albertel  276:  my @pars = ();
1.372     albertel  277:  my $pwd=$env{'request.filename'};
1.23      albertel  278:  $pwd =~ s:/[^/]*$::;
                    279:  &newparser(\@pars,\$content_file_string,$pwd);
1.24      sakharuk  280: 
1.3       sakharuk  281:  my $safeeval = new Safe;
1.40      albertel  282:  my $safehole = new Safe::Hole;
1.82      ng        283:  &init_safespace($target,$safeeval,$safehole,$safeinit);
1.3       sakharuk  284: #-------------------- Redefinition of the target in the case of compound target
                    285: 
                    286:  ($target, my @tenta) = split('&&',$target);
                    287: 
1.150     albertel  288:  my @stack = ();
1.3       sakharuk  289:  my @parstack = ();
1.358     albertel  290:  &initdepth();
                    291:  &init_alarm();
1.101     albertel  292:  my $finaloutput = &inner_xmlparse($target,\@stack,\@parstack,\@pars,
1.394     albertel  293: 				   $safeeval,\%style_for_target,1);
1.255     sakharuk  294: 
1.425     albertel  295:  if (@stack) {
1.482     bisitz    296:      &warning(&mt('At end of file some tags were still left unclosed:').
                    297: 	      ' <tt>&lt;'.join('&gt;</tt>, <tt>&lt;',reverse(@stack)).
1.425     albertel  298: 	      '&gt;</tt>');
                    299:  }
1.372     albertel  300:  if ($env{'request.uri'}) {
                    301:     &writeallows($env{'request.uri'});
1.125     www       302:  }
1.281     albertel  303:  &do_registered_ssi();
1.204     albertel  304:  if ($Apache::lonxml::counter_changed) { &store_counter() }
1.393     albertel  305: 
                    306:  &clean_safespace($safeeval);
                    307: 
1.448     albertel  308:  if (@script_var_displays) {
1.527     www       309:      my $scriptoutput = join('',@script_var_displays);
                    310:      $finaloutput=~s{(</body>\s*</html>)\s*$}{$scriptoutput$1}s;
1.448     albertel  311:      undef(@script_var_displays);
                    312:  }
1.469     albertel  313:  &init_state();
1.372     albertel  314:  if ($env{'form.return_only_error_and_warning_counts'}) {
1.473     www       315:      if ($env{'request.filename'}=~/\.(html|htm|xml)$/i) { 
                    316:         my $error=&verify_html($content_file_string);
                    317:         if ($error) { $errorcount++; }
                    318:      }
1.361     www       319:      return "$errorcount:$warningcount";
                    320:  }
1.3       sakharuk  321:  return $finaloutput;
1.106     www       322: }
                    323: 
1.191     albertel  324: sub latex_special_symbols {
1.272     albertel  325:     my ($string,$where)=@_;
1.396     foxr      326:     #
                    327:     #  If e.g. in verbatim mode, then don't substitute.
                    328:     #  but return original string.
                    329:     #
                    330:     if (!($Apache::lonxml::substitute_LaTeX_symbols)) {
                    331: 	return $string;
                    332:     }
1.235     sakharuk  333:     if ($where eq 'header') {
1.414     foxr      334: 	$string =~ s/\\/\$\\backslash\$/g; # \  -> $\backslash$ per LaTex line by line pg  10.
1.311     albertel  335: 	$string =~ s/(\$|%|\{|\})/\\$1/g;
                    336: 	$string=&Apache::lonprintout::character_chart($string);
                    337: 	# any & or # leftover should be safe to just escape
                    338:         $string=~s/([^\\])\&/$1\\\&/g;
                    339:         $string=~s/([^\\])\#/$1\\\#/g;
1.415     foxr      340: 	$string =~ s/_/\\_/g;              # _ -> \_
                    341: 	$string =~ s/\^/\\\^{}/g;          # ^ -> \^{} 
1.229     sakharuk  342:     } else {
1.312     albertel  343: 	$string=~s/\\/\\ensuremath{\\backslash}/g;
1.367     albertel  344: 	$string=~s/\\\%|\%/\\\%/g;
                    345: 	$string=~s/\\{|{/\\{/g;
                    346: 	$string=~s/\\}|}/\\}/g;
1.378     albertel  347: 	$string=~s/\\ensuremath\\{\\backslash\\}/\\ensuremath{\\backslash}/g;
1.367     albertel  348: 	$string=~s/\\\$|\$/\\\$/g;
                    349: 	$string=~s/\\\_|\_/\\\_/g;
1.313     albertel  350:         $string=~s/([^\\]|^)(\~|\^)/$1\\$2\\strut /g;
1.310     sakharuk  351: 	$string=~s/(>|<)/\\ensuremath\{$1\}/g; #more or less
1.311     albertel  352: 	$string=&Apache::lonprintout::character_chart($string);
                    353: 	# any & or # leftover should be safe to just escape
1.367     albertel  354: 	$string=~s/\\\&|\&/\\\&/g;
                    355: 	$string=~s/\\\#|\#/\\\#/g;
1.332     sakharuk  356:         $string=~s/\|/\$\\mid\$/g;
1.310     sakharuk  357: #single { or } How to escape?
1.229     sakharuk  358:     }
1.272     albertel  359:     return $string;
1.188     sakharuk  360: }
                    361: 
1.101     albertel  362: sub inner_xmlparse {
1.394     albertel  363:   my ($target,$stack,$parstack,$pars,$safeeval,$style_for_target,$start)=@_;
1.101     albertel  364:   my $finaloutput = '';
                    365:   my $result;
                    366:   my $token;
1.258     albertel  367:   my $dontpop=0;
1.389     albertel  368:   my $startredirection = $Apache::lonxml::redirection;
1.101     albertel  369:   while ( $#$pars > -1 ) {
                    370:     while ($token = $$pars['-1']->get_token) {
1.261     albertel  371:       if (($token->[0] eq 'T') || ($token->[0] eq 'C') ) {
1.101     albertel  372: 	if ($metamode<1) {
1.190     albertel  373: 	    my $text=$token->[1];
1.193     albertel  374: 	    if ($token->[0] eq 'C' && $target eq 'tex') {
1.239     sakharuk  375: 		$text = '';
                    376: #		$text = '%'.$text."\n";
1.182     sakharuk  377: 	    }
1.190     albertel  378: 	    $result.=$text;
1.101     albertel  379: 	}
1.261     albertel  380:       } elsif (($token->[0] eq 'D')) {
                    381: 	if ($metamode<1 && $target eq 'web') {
                    382: 	    my $text=$token->[1];
                    383: 	    $result.=$text;
                    384: 	}
1.101     albertel  385:       } elsif ($token->[0] eq 'PI') {
1.261     albertel  386: 	if ($metamode<1 && $target eq 'web') {
1.101     albertel  387: 	  $result=$token->[2];
                    388: 	}
                    389:       } elsif ($token->[0] eq 'S') {
1.140     albertel  390: 	# add tag to stack
1.101     albertel  391: 	push (@$stack,$token->[1]);
                    392: 	# add parameters list to another stack
                    393: 	push (@$parstack,&parstring($token));
1.140     albertel  394: 	&increasedepth($token);
1.212     albertel  395: 	if ($Apache::lonxml::usestyle &&
                    396: 	    exists($$style_for_target{$token->[1]})) {
                    397: 	    $Apache::lonxml::usestyle=0;
                    398: 	    my $string=$$style_for_target{$token->[1]}.
                    399: 	      '<LONCAPA_INTERNAL_TURN_STYLE_ON />';
                    400: 	    &Apache::lonxml::newparser($pars,\$string);
1.257     albertel  401: 	    $Apache::lonxml::style_values=$$parstack[-1];
1.259     albertel  402: 	    $Apache::lonxml::style_end_values=$$parstack[-1];
1.101     albertel  403: 	} else {
                    404: 	  $result = &callsub("start_$token->[1]", $target, $token, $stack,
                    405: 			     $parstack, $pars, $safeeval, $style_for_target);
1.140     albertel  406: 	}
1.101     albertel  407:       } elsif ($token->[0] eq 'E') {
1.212     albertel  408: 	if ($Apache::lonxml::usestyle &&
                    409: 	    exists($$style_for_target{'/'."$token->[1]"})) {
                    410: 	    $Apache::lonxml::usestyle=0;
                    411: 	    my $string=$$style_for_target{'/'.$token->[1]}.
1.258     albertel  412: 	      '<LONCAPA_INTERNAL_TURN_STYLE_ON end="'.$token->[1].'" />';
1.212     albertel  413: 	    &Apache::lonxml::newparser($pars,\$string);
1.259     albertel  414: 	    $Apache::lonxml::style_values=$Apache::lonxml::style_end_values;
                    415: 	    $Apache::lonxml::style_end_values='';
1.258     albertel  416: 	    $dontpop=1;
1.101     albertel  417: 	} else {
1.258     albertel  418: 	    #clear out any tags that didn't end
                    419: 	    while ($token->[1] ne $$stack['-1'] && ($#$stack > -1)) {
                    420: 		my $lasttag=$$stack[-1];
1.317     albertel  421: 		if ($token->[1] =~ /^\Q$lasttag\E$/i) {
1.483     bisitz    422: 		    &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;'));
1.258     albertel  423: 		    last;
                    424: 		} else {
1.483     bisitz    425:                     &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;'));
1.258     albertel  426: 		    &end_tag($stack,$parstack,$token);
                    427: 		}
                    428: 	    }
                    429: 	    $result = &callsub("end_$token->[1]", $target, $token, $stack,
                    430: 			       $parstack, $pars,$safeeval, $style_for_target);
1.101     albertel  431: 	}
                    432:       } else {
                    433: 	&Apache::lonxml::error("Unknown token event :$token->[0]:$token->[1]:");
                    434:       }
                    435:       #evaluate variable refs in result
1.282     albertel  436:       if ($Apache::lonxml::post_evaluate &&$result ne "") {
1.257     albertel  437: 	  my $extras;
                    438: 	  if (!$Apache::lonxml::usestyle) {
                    439: 	      $extras=$Apache::lonxml::style_values;
                    440: 	  }
1.488     raeburn   441: 	  if ( $#$parstack > -1 ) {
                    442: 	      $result=&Apache::run::evaluate($result,$safeeval,$extras.$$parstack[-1]);
                    443: 	  } else {
                    444: 	      $result= &Apache::run::evaluate($result,$safeeval,$extras);
1.487     raeburn   445:           }
1.163     albertel  446:       }
1.282     albertel  447:       $Apache::lonxml::post_evaluate=1;
                    448: 
1.190     albertel  449:       if (($token->[0] eq 'T') || ($token->[0] eq 'C') || ($token->[0] eq 'D') ) {
1.249     albertel  450: 	  #Style file definitions should be correct
1.250     albertel  451: 	  if ($target eq 'tex' && ($Apache::lonxml::usestyle)) {
1.311     albertel  452: 	      $result=&latex_special_symbols($result);
1.249     albertel  453: 	  }
1.190     albertel  454:       }
                    455: 
1.169     albertel  456:       if ($Apache::lonxml::redirection) {
                    457: 	$Apache::lonxml::outputstack['-1'] .= $result;
                    458:       } else {
                    459: 	$finaloutput.=$result;
                    460:       }
                    461:       $result = '';
                    462: 
1.258     albertel  463:       if ($token->[0] eq 'E' && !$dontpop) {
1.101     albertel  464: 	&end_tag($stack,$parstack,$token);
                    465:       }
1.258     albertel  466:       $dontpop=0;
1.224     albertel  467:     }	
1.212     albertel  468:     if ($#$pars > -1) {
                    469: 	pop @$pars;
                    470: 	pop @Apache::lonxml::pwd;
                    471:     }
1.101     albertel  472:   }
                    473: 
                    474:   # if ($target eq 'meta') {
                    475:   #   $finaloutput.=&endredirection;
                    476:   # }
                    477: 
1.394     albertel  478:   if ( $start && $target eq 'grade') { &endredirection(); }
1.389     albertel  479:   if ( $Apache::lonxml::redirection > $startredirection) {
                    480:       while ($Apache::lonxml::redirection > $startredirection) {
                    481: 	  $finaloutput .= &endredirection();
1.387     albertel  482:       }
                    483:   }
1.101     albertel  484:   if (($ENV{'QUERY_STRING'}) && ($target eq 'web')) {
                    485:     $finaloutput=&afterburn($finaloutput);
1.509     www       486:   }
                    487:   if ($target eq 'modified') {
                    488: # if modfied, handle startpart and endpart
                    489:      $finaloutput=~s/\<startpartmarker[^\>]*\>(.*)\<endpartmarker[^\>]*\>/<part>$1<\/part>/gs;
1.216     sakharuk  490:   }	    
1.101     albertel  491:   return $finaloutput;
                    492: }
1.67      www       493: 
1.318     matthew   494: ## 
                    495: ## Looks to see if there is a subroutine defined for this tag.  If so, call it,
                    496: ## otherwise do not call it as we do not know what it is.
                    497: ##
1.7       albertel  498: sub callsub {
1.84      albertel  499:   my ($sub,$target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
1.7       albertel  500:   my $currentstring='';
1.72      albertel  501:   my $nodefault;
1.7       albertel  502:   {
1.59      albertel  503:     my $sub1;
1.7       albertel  504:     no strict 'refs';
1.68      www       505:     my $tag=$token->[1];
1.236     www       506: # get utterly rid of extended html tags
                    507:     if ($tag=~/^x\-/i) { return ''; }
1.141     albertel  508:     my $space=$Apache::lonxml::alltags{$tag}[-1];
1.68      www       509:     if (!$space) {
1.141     albertel  510:      	$tag=~tr/A-Z/a-z/;
1.68      www       511: 	$sub=~tr/A-Z/a-z/;
1.141     albertel  512: 	$space=$Apache::lonxml::alltags{$tag}[-1]
1.68      www       513:     }
1.97      albertel  514: 
                    515:     my $deleted=0;
                    516:     if (($token->[0] eq 'S') && ($target eq 'modified')) {
                    517:       $deleted=&Apache::edit::handle_delete($space,$target,$token,$tagstack,
                    518: 					     $parstack,$parser,$safeeval,
                    519: 					     $style);
                    520:     }
                    521:     if (!$deleted) {
                    522:       if ($space) {
1.220     albertel  523: 	#&Apache::lonxml::debug("Calling sub $sub in $space $metamode");
1.97      albertel  524: 	$sub1="$space\:\:$sub";
                    525: 	($currentstring,$nodefault) = &$sub1($target,$token,$tagstack,
                    526: 					     $parstack,$parser,$safeeval,
                    527: 					     $style);
                    528:       } else {
1.318     matthew   529:           if ($target eq 'tex') {
                    530:               # throw away tag name
                    531:               return '';
                    532:           }
1.220     albertel  533: 	#&Apache::lonxml::debug("NOT Calling sub $sub in $space $metamode");
1.97      albertel  534: 	if ($metamode <1) {
                    535: 	  if (defined($token->[4]) && ($metamode < 1)) {
                    536: 	    $currentstring = $token->[4];
                    537: 	  } else {
                    538: 	    $currentstring = $token->[2];
                    539: 	  }
1.62      sakharuk  540: 	}
1.7       albertel  541:       }
1.97      albertel  542:       #    &Apache::lonxml::debug("nodefalt:$nodefault:");
                    543:       if ($currentstring eq '' && $nodefault eq '') {
                    544: 	if ($target eq 'edit') {
1.220     albertel  545: 	  #&Apache::lonxml::debug("doing default edit for $token->[1]");
1.97      albertel  546: 	  if ($token->[0] eq 'S') {
                    547: 	    $currentstring = &Apache::edit::tag_start($target,$token);
                    548: 	  } elsif ($token->[0] eq 'E') {
                    549: 	    $currentstring = &Apache::edit::tag_end($target,$token);
                    550: 	  }
1.441     albertel  551: 	}
                    552:       }
                    553:       if ($target eq 'modified' && $nodefault eq '') {
                    554: 	  if ($currentstring eq '') {
                    555: 	      if ($token->[0] eq 'S') {
                    556: 		  $currentstring = $token->[4];
                    557: 	      } elsif ($token->[0] eq 'E') {
                    558: 		  $currentstring = $token->[2];
                    559: 	      } else {
                    560: 		  $currentstring = $token->[2];
                    561: 	      }
                    562: 	  }
1.97      albertel  563: 	  if ($token->[0] eq 'S') {
1.447     albertel  564: 	      $currentstring.=&Apache::edit::handle_insert();
1.210     www       565: 	  } elsif ($token->[0] eq 'E') {
1.447     albertel  566: 	      $currentstring.=&Apache::edit::handle_insertafter($token->[1]);
1.97      albertel  567: 	  }
1.72      albertel  568:       }
1.7       albertel  569:     }
                    570:     use strict 'refs';
                    571:   }
                    572:   return $currentstring;
1.82      ng        573: }
                    574: 
1.465     albertel  575: {
                    576:     my %state;
                    577: 
                    578:     sub init_state {
                    579: 	undef(%state);
                    580:     }
                    581:     
                    582:     sub set_state {
                    583: 	my ($key,$value) = @_;
                    584: 	$state{$key} = $value;
                    585: 	return $value;
                    586:     }
                    587:     sub get_state {
                    588: 	my ($key) = @_;
                    589: 	return $state{$key};
                    590:     }
                    591: }
                    592: 
1.96      albertel  593: sub setup_globals {
1.172     albertel  594:   my ($request,$target)=@_;
                    595:   $Apache::lonxml::request=$request;
1.205     www       596:   $errorcount=0;
                    597:   $warningcount=0;
1.490     www       598:   $Apache::lonxml::internal_error=0;
1.207     albertel  599:   $Apache::lonxml::default_homework_loaded=0;
1.212     albertel  600:   $Apache::lonxml::usestyle=1;
1.204     albertel  601:   &init_counter();
1.462     foxr      602:   &clear_bubble_lines_for_part();
1.465     albertel  603:   &init_state();
1.469     albertel  604:   &set_state('target',$target);
1.101     albertel  605:   @Apache::lonxml::pwd=();
1.124     albertel  606:   @Apache::lonxml::extlinks=();
1.448     albertel  607:   @script_var_displays=();
1.281     albertel  608:   @Apache::lonxml::ssi_info=();
1.282     albertel  609:   $Apache::lonxml::post_evaluate=1;
1.295     albertel  610:   $Apache::lonxml::warnings_error_header='';
1.397     albertel  611:   $Apache::lonxml::substitute_LaTeX_symbols = 1;
1.96      albertel  612:   if ($target eq 'meta') {
                    613:     $Apache::lonxml::redirection = 0;
                    614:     $Apache::lonxml::metamode = 1;
                    615:     $Apache::lonxml::evaluate = 1;
                    616:     $Apache::lonxml::import = 0;
1.129     albertel  617:   } elsif ($target eq 'answer') {
                    618:     $Apache::lonxml::redirection = 0;
                    619:     $Apache::lonxml::metamode = 1;
                    620:     $Apache::lonxml::evaluate = 1;
                    621:     $Apache::lonxml::import = 1;
1.96      albertel  622:   } elsif ($target eq 'grade') {
1.387     albertel  623:     &startredirection(); #ended in inner_xmlparse on exit
1.96      albertel  624:     $Apache::lonxml::metamode = 0;
                    625:     $Apache::lonxml::evaluate = 1;
                    626:     $Apache::lonxml::import = 1;
                    627:   } elsif ($target eq 'modified') {
                    628:     $Apache::lonxml::redirection = 0;
                    629:     $Apache::lonxml::metamode = 0;
                    630:     $Apache::lonxml::evaluate = 0;
                    631:     $Apache::lonxml::import = 0;
                    632:   } elsif ($target eq 'edit') {
                    633:     $Apache::lonxml::redirection = 0;
                    634:     $Apache::lonxml::metamode = 0;
                    635:     $Apache::lonxml::evaluate = 0;
                    636:     $Apache::lonxml::import = 0;
1.163     albertel  637:   } elsif ($target eq 'analyze') {
                    638:     $Apache::lonxml::redirection = 0;
                    639:     $Apache::lonxml::metamode = 0;
                    640:     $Apache::lonxml::evaluate = 1;
                    641:     $Apache::lonxml::import = 1;
1.96      albertel  642:   } else {
                    643:     $Apache::lonxml::redirection = 0;
                    644:     $Apache::lonxml::metamode = 0;
                    645:     $Apache::lonxml::evaluate = 1;
                    646:     $Apache::lonxml::import = 1;
                    647:   }
                    648: }
                    649: 
1.82      ng        650: sub init_safespace {
                    651:   my ($target,$safeeval,$safehole,$safeinit) = @_;
1.511     foxr      652:   $safeeval->reval('use LaTeX::Table;');
1.393     albertel  653:   $safeeval->deny_only(':dangerous');
1.533     raeburn   654:   $safeeval->reval('use Math::Complex;');
1.383     albertel  655:   $safeeval->permit_only(":default");
1.82      ng        656:   $safeeval->permit("entereval");
                    657:   $safeeval->permit(":base_math");
                    658:   $safeeval->permit("sort");
1.286     albertel  659:   $safeeval->permit("time");
1.480     www       660:   $safeeval->permit("caller");
1.371     albertel  661:   $safeeval->deny("rand");
                    662:   $safeeval->deny("srand");
1.82      ng        663:   $safeeval->deny(":base_io");
1.102     albertel  664:   $safehole->wrap(\&Apache::scripttag::xmlparse,$safeeval,'&xmlparse');
1.251     albertel  665:   $safehole->wrap(\&Apache::outputtags::multipart,$safeeval,'&multipart');
1.82      ng        666:   $safehole->wrap(\&Apache::lonnet::EXT,$safeeval,'&EXT');
1.324     albertel  667:   $safehole->wrap(\&Apache::chemresponse::chem_standard_order,$safeeval,
                    668: 		  '&chem_standard_order');
1.369     albertel  669:   $safehole->wrap(\&Apache::response::check_status,$safeeval,'&check_status');
1.471     bisitz    670:   $safehole->wrap(\&Apache::response::implicit_multiplication,$safeeval,'&implicit_multiplication');
1.324     albertel  671: 
1.431     www       672:   $safehole->wrap(\&Apache::lonmaxima::maxima_eval,$safeeval,'&maxima_eval');
1.432     www       673:   $safehole->wrap(\&Apache::lonmaxima::maxima_check,$safeeval,'&maxima_check');
1.433     albertel  674:   $safehole->wrap(\&Apache::lonmaxima::maxima_cas_formula_fix,$safeeval,
                    675: 		  '&maxima_cas_formula_fix');
                    676: 
1.494     www       677:   $safehole->wrap(\&Apache::lonr::r_eval,$safeeval,'&r_eval');
1.497     www       678:   $safehole->wrap(\&Apache::lonr::Rentry,$safeeval,'&Rentry');
                    679:   $safehole->wrap(\&Apache::lonr::Rarray,$safeeval,'&Rarray');
1.494     www       680:   $safehole->wrap(\&Apache::lonr::r_check,$safeeval,'&r_check');
                    681:   $safehole->wrap(\&Apache::lonr::r_cas_formula_fix,$safeeval,
                    682:                   '&r_cas_formula_fix');
                    683:  
1.433     albertel  684:   $safehole->wrap(\&Apache::caparesponse::capa_formula_fix,$safeeval,
                    685: 		  '&capa_formula_fix');
1.431     www       686: 
1.480     www       687:   $safehole->wrap(\&Apache::lonlocal::locallocaltime,$safeeval,
                    688:                   '&locallocaltime');
                    689: 
1.82      ng        690:   $safehole->wrap(\&Math::Cephes::asin,$safeeval,'&asin');
                    691:   $safehole->wrap(\&Math::Cephes::acos,$safeeval,'&acos');
                    692:   $safehole->wrap(\&Math::Cephes::atan,$safeeval,'&atan');
                    693:   $safehole->wrap(\&Math::Cephes::sinh,$safeeval,'&sinh');
                    694:   $safehole->wrap(\&Math::Cephes::cosh,$safeeval,'&cosh');
                    695:   $safehole->wrap(\&Math::Cephes::tanh,$safeeval,'&tanh');
                    696:   $safehole->wrap(\&Math::Cephes::asinh,$safeeval,'&asinh');
                    697:   $safehole->wrap(\&Math::Cephes::acosh,$safeeval,'&acosh');
                    698:   $safehole->wrap(\&Math::Cephes::atanh,$safeeval,'&atanh');
                    699:   $safehole->wrap(\&Math::Cephes::erf,$safeeval,'&erf');
                    700:   $safehole->wrap(\&Math::Cephes::erfc,$safeeval,'&erfc');
                    701:   $safehole->wrap(\&Math::Cephes::j0,$safeeval,'&j0');
                    702:   $safehole->wrap(\&Math::Cephes::j1,$safeeval,'&j1');
                    703:   $safehole->wrap(\&Math::Cephes::jn,$safeeval,'&jn');
                    704:   $safehole->wrap(\&Math::Cephes::jv,$safeeval,'&jv');
                    705:   $safehole->wrap(\&Math::Cephes::y0,$safeeval,'&y0');
                    706:   $safehole->wrap(\&Math::Cephes::y1,$safeeval,'&y1');
                    707:   $safehole->wrap(\&Math::Cephes::yn,$safeeval,'&yn');
                    708:   $safehole->wrap(\&Math::Cephes::yv,$safeeval,'&yv');
1.215     albertel  709:   
                    710:   $safehole->wrap(\&Math::Cephes::bdtr  ,$safeeval,'&bdtr'  );
                    711:   $safehole->wrap(\&Math::Cephes::bdtrc ,$safeeval,'&bdtrc' );
                    712:   $safehole->wrap(\&Math::Cephes::bdtri ,$safeeval,'&bdtri' );
                    713:   $safehole->wrap(\&Math::Cephes::btdtr ,$safeeval,'&btdtr' );
                    714:   $safehole->wrap(\&Math::Cephes::chdtr ,$safeeval,'&chdtr' );
                    715:   $safehole->wrap(\&Math::Cephes::chdtrc,$safeeval,'&chdtrc');
                    716:   $safehole->wrap(\&Math::Cephes::chdtri,$safeeval,'&chdtri');
                    717:   $safehole->wrap(\&Math::Cephes::fdtr  ,$safeeval,'&fdtr'  );
                    718:   $safehole->wrap(\&Math::Cephes::fdtrc ,$safeeval,'&fdtrc' );
                    719:   $safehole->wrap(\&Math::Cephes::fdtri ,$safeeval,'&fdtri' );
                    720:   $safehole->wrap(\&Math::Cephes::gdtr  ,$safeeval,'&gdtr'  );
                    721:   $safehole->wrap(\&Math::Cephes::gdtrc ,$safeeval,'&gdtrc' );
                    722:   $safehole->wrap(\&Math::Cephes::nbdtr ,$safeeval,'&nbdtr' );
                    723:   $safehole->wrap(\&Math::Cephes::nbdtrc,$safeeval,'&nbdtrc');
                    724:   $safehole->wrap(\&Math::Cephes::nbdtri,$safeeval,'&nbdtri');
                    725:   $safehole->wrap(\&Math::Cephes::ndtr  ,$safeeval,'&ndtr'  );
                    726:   $safehole->wrap(\&Math::Cephes::ndtri ,$safeeval,'&ndtri' );
                    727:   $safehole->wrap(\&Math::Cephes::pdtr  ,$safeeval,'&pdtr'  );
                    728:   $safehole->wrap(\&Math::Cephes::pdtrc ,$safeeval,'&pdtrc' );
                    729:   $safehole->wrap(\&Math::Cephes::pdtri ,$safeeval,'&pdtri' );
                    730:   $safehole->wrap(\&Math::Cephes::stdtr ,$safeeval,'&stdtr' );
                    731:   $safehole->wrap(\&Math::Cephes::stdtri,$safeeval,'&stdtri');
                    732: 
1.383     albertel  733:   $safehole->wrap(\&Math::Cephes::Matrix::mat,$safeeval,'&mat');
                    734:   $safehole->wrap(\&Math::Cephes::Matrix::new,$safeeval,
                    735: 		  '&Math::Cephes::Matrix::new');
                    736:   $safehole->wrap(\&Math::Cephes::Matrix::coef,$safeeval,
                    737: 		  '&Math::Cephes::Matrix::coef');
                    738:   $safehole->wrap(\&Math::Cephes::Matrix::clr,$safeeval,
                    739: 		  '&Math::Cephes::Matrix::clr');
                    740:   $safehole->wrap(\&Math::Cephes::Matrix::add,$safeeval,
                    741: 		  '&Math::Cephes::Matrix::add');
                    742:   $safehole->wrap(\&Math::Cephes::Matrix::sub,$safeeval,
                    743: 		  '&Math::Cephes::Matrix::sub');
                    744:   $safehole->wrap(\&Math::Cephes::Matrix::mul,$safeeval,
                    745: 		  '&Math::Cephes::Matrix::mul');
                    746:   $safehole->wrap(\&Math::Cephes::Matrix::div,$safeeval,
                    747: 		  '&Math::Cephes::Matrix::div');
                    748:   $safehole->wrap(\&Math::Cephes::Matrix::inv,$safeeval,
                    749: 		  '&Math::Cephes::Matrix::inv');
                    750:   $safehole->wrap(\&Math::Cephes::Matrix::transp,$safeeval,
                    751: 		  '&Math::Cephes::Matrix::transp');
                    752:   $safehole->wrap(\&Math::Cephes::Matrix::simq,$safeeval,
                    753: 		  '&Math::Cephes::Matrix::simq');
                    754:   $safehole->wrap(\&Math::Cephes::Matrix::mat_to_vec,$safeeval,
                    755: 		  '&Math::Cephes::Matrix::mat_to_vec');
                    756:   $safehole->wrap(\&Math::Cephes::Matrix::vec_to_mat,$safeeval,
                    757: 		  '&Math::Cephes::Matrix::vec_to_mat');
                    758:   $safehole->wrap(\&Math::Cephes::Matrix::check,$safeeval,
                    759: 		  '&Math::Cephes::Matrix::check');
                    760:   $safehole->wrap(\&Math::Cephes::Matrix::check,$safeeval,
                    761: 		  '&Math::Cephes::Matrix::check');
                    762: 
1.215     albertel  763: #  $safehole->wrap(\&Math::Cephes::new_fract,$safeeval,'&new_fract');
                    764: #  $safehole->wrap(\&Math::Cephes::radd,$safeeval,'&radd');
                    765: #  $safehole->wrap(\&Math::Cephes::rsub,$safeeval,'&rsub');
                    766: #  $safehole->wrap(\&Math::Cephes::rmul,$safeeval,'&rmul');
                    767: #  $safehole->wrap(\&Math::Cephes::rdiv,$safeeval,'&rdiv');
                    768: #  $safehole->wrap(\&Math::Cephes::euclid,$safeeval,'&euclid');
                    769: 
1.91      ng        770:   $safehole->wrap(\&Math::Random::random_beta,$safeeval,'&math_random_beta');
                    771:   $safehole->wrap(\&Math::Random::random_chi_square,$safeeval,'&math_random_chi_square');
                    772:   $safehole->wrap(\&Math::Random::random_exponential,$safeeval,'&math_random_exponential');
                    773:   $safehole->wrap(\&Math::Random::random_f,$safeeval,'&math_random_f');
                    774:   $safehole->wrap(\&Math::Random::random_gamma,$safeeval,'&math_random_gamma');
                    775:   $safehole->wrap(\&Math::Random::random_multivariate_normal,$safeeval,'&math_random_multivariate_normal');
                    776:   $safehole->wrap(\&Math::Random::random_multinomial,$safeeval,'&math_random_multinomial');
                    777:   $safehole->wrap(\&Math::Random::random_noncentral_chi_square,$safeeval,'&math_random_noncentral_chi_square');
                    778:   $safehole->wrap(\&Math::Random::random_noncentral_f,$safeeval,'&math_random_noncentral_f');
                    779:   $safehole->wrap(\&Math::Random::random_normal,$safeeval,'&math_random_normal');
                    780:   $safehole->wrap(\&Math::Random::random_permutation,$safeeval,'&math_random_permutation');
1.93      ng        781:   $safehole->wrap(\&Math::Random::random_permuted_index,$safeeval,'&math_random_permuted_index');
1.91      ng        782:   $safehole->wrap(\&Math::Random::random_uniform,$safeeval,'&math_random_uniform');
                    783:   $safehole->wrap(\&Math::Random::random_poisson,$safeeval,'&math_random_poisson');
                    784:   $safehole->wrap(\&Math::Random::random_uniform_integer,$safeeval,'&math_random_uniform_integer');
                    785:   $safehole->wrap(\&Math::Random::random_negative_binomial,$safeeval,'&math_random_negative_binomial');
                    786:   $safehole->wrap(\&Math::Random::random_binomial,$safeeval,'&math_random_binomial');
                    787:   $safehole->wrap(\&Math::Random::random_seed_from_phrase,$safeeval,'&random_seed_from_phrase');
                    788:   $safehole->wrap(\&Math::Random::random_set_seed_from_phrase,$safeeval,'&random_set_seed_from_phrase');
                    789:   $safehole->wrap(\&Math::Random::random_get_seed,$safeeval,'&random_get_seed');
                    790:   $safehole->wrap(\&Math::Random::random_set_seed,$safeeval,'&random_set_seed');
1.458     albertel  791:   $safehole->wrap(\&Apache::loncommon::languages,$safeeval,'&languages');
1.305     albertel  792:   $safehole->wrap(\&Apache::lonxml::error,$safeeval,'&LONCAPA_INTERNAL_ERROR');
1.311     albertel  793:   $safehole->wrap(\&Apache::lonxml::debug,$safeeval,'&LONCAPA_INTERNAL_DEBUG');
1.420     albertel  794:   $safehole->wrap(\&Apache::lonnet::logthis,$safeeval,'&LONCAPA_INTERNAL_LOGTHIS');
                    795:   $safehole->wrap(\&Apache::inputtags::finalizeawards,$safeeval,'&LONCAPA_INTERNAL_FINALIZEAWARDS');
1.322     albertel  796:   $safehole->wrap(\&Apache::caparesponse::get_sigrange,$safeeval,'&LONCAPA_INTERNAL_get_sigrange');
1.521     www       797:   $safehole->wrap(\&Apache::functionplotresponse::fpr_val,$safeeval,'&fpr_val');
1.520     www       798:   $safehole->wrap(\&Apache::functionplotresponse::fpr_f,$safeeval,'&fpr_f');
                    799:   $safehole->wrap(\&Apache::functionplotresponse::fpr_dfdx,$safeeval,'&fpr_dfdx');
                    800:   $safehole->wrap(\&Apache::functionplotresponse::fpr_d2fdx2,$safeeval,'&fpr_d2fdx2');
1.524     www       801:   $safehole->wrap(\&Apache::functionplotresponse::fpr_vectorcoords,$safeeval,'&fpr_vectorcoords');
                    802:   $safehole->wrap(\&Apache::functionplotresponse::fpr_objectcoords,$safeeval,'&fpr_objectcoords');
                    803:   $safehole->wrap(\&Apache::functionplotresponse::fpr_vectorlength,$safeeval,'&fpr_vectorlength');
                    804:   $safehole->wrap(\&Apache::functionplotresponse::fpr_vectorangle,$safeeval,'&fpr_vectorangle');
1.520     www       805: 
1.430     albertel  806: #  use Data::Dumper;
                    807: #  $safehole->wrap(\&Data::Dumper::Dumper,$safeeval,'&LONCAPA_INTERNAL_Dumper');
1.82      ng        808: #need to inspect this class of ops
                    809: # $safeeval->deny(":base_orig");
1.331     albertel  810:   $safeeval->permit("require");
1.91      ng        811:   $safeinit .= ';$external::target="'.$target.'";';
1.82      ng        812:   &Apache::run::run($safeinit,$safeeval);
1.373     albertel  813:   &initialize_rndseed($safeeval);
                    814: }
1.303     albertel  815: 
1.393     albertel  816: sub clean_safespace {
                    817:     my ($safeeval) = @_;
                    818:     delete_package_recurse($safeeval->{Root});
                    819: }
                    820: 
                    821: sub delete_package_recurse {
                    822:      my ($package) = @_;
                    823:      my @subp;
                    824:      {
                    825: 	 no strict 'refs';
                    826: 	 while (my ($key,$val) = each(%{*{"$package\::"}})) {
                    827: 	     if (!defined($val)) { next; }
                    828: 	     local (*ENTRY) = $val;
                    829: 	     if (defined *ENTRY{HASH} && $key =~ /::$/ &&
                    830: 		 $key ne "main::" && $key ne "<none>::")
                    831: 	     {
                    832: 		 my ($p) = $package ne "main" ? "$package\::" : "";
                    833: 		 ($p .= $key) =~ s/::$//;
                    834: 		 push(@subp,$p);
                    835: 	     }
                    836: 	 }
                    837:      }
                    838:      foreach my $p (@subp) {
                    839: 	 delete_package_recurse($p);
                    840:      }
                    841:      Symbol::delete_package($package);
                    842: }
                    843: 
1.373     albertel  844: sub initialize_rndseed {
                    845:     my ($safeeval)=@_;
                    846:     my $rndseed;
1.423     albertel  847:     my ($symb,$courseid,$domain,$name) = &Apache::lonnet::whichuser();
1.373     albertel  848:     $rndseed=&Apache::lonnet::rndseed($symb,$courseid,$domain,$name);
                    849:     my $safeinit = '$external::randomseed="'.$rndseed.'";';
                    850:     &Apache::lonxml::debug("Setting rndseed to $rndseed");
                    851:     &Apache::run::run($safeinit,$safeeval);
1.207     albertel  852: }
                    853: 
                    854: sub default_homework_load {
                    855:     my ($safeeval)=@_;
                    856:     &Apache::lonxml::debug('Loading default_homework');
1.522     raeburn   857:     my $default=&Apache::lonnet::getfile($Apache::lonnet::perlvar{'lonIncludes'}.
                    858:                                          '/default_homework.lcpm');
1.241     albertel  859:     if ($default eq -1) {
1.207     albertel  860: 	&Apache::lonxml::error("<b>Unable to find <i>default_homework.lcpm</i></b>");
                    861:     } else {
                    862: 	&Apache::run::run($default,$safeeval);
                    863: 	$Apache::lonxml::default_homework_loaded=1;
                    864:     }
1.17      albertel  865: }
                    866: 
1.358     albertel  867: {
                    868:     my $alarm_depth;
                    869:     sub init_alarm {
                    870: 	alarm(0);
                    871: 	$alarm_depth=0;
                    872:     }
                    873: 
                    874:     sub start_alarm {
                    875: 	if ($alarm_depth<1) {
                    876: 	    my $old=alarm($Apache::lonnet::perlvar{'lonScriptTimeout'});
                    877: 	    if ($old) {
                    878: 		&Apache::lonxml::error("Cancelled an alarm of $old, this shouldn't occur.");
                    879: 	    }
                    880: 	}
                    881: 	$alarm_depth++;
                    882:     }
                    883: 
                    884:     sub end_alarm {
                    885: 	$alarm_depth--;
                    886: 	if ($alarm_depth<1) { alarm(0); }
                    887:     }
                    888: }
1.328     albertel  889: my $metamode_was;
1.55      albertel  890: sub startredirection {
1.328     albertel  891:     if (!$Apache::lonxml::redirection) {
                    892: 	$metamode_was=$Apache::lonxml::metamode;
                    893:     }
                    894:     $Apache::lonxml::metamode=0;
                    895:     $Apache::lonxml::redirection++;
                    896:     push (@Apache::lonxml::outputstack, '');
1.55      albertel  897: }
                    898: 
                    899: sub endredirection {
1.328     albertel  900:     if (!$Apache::lonxml::redirection) {
1.380     www       901: 	&Apache::lonxml::error("Endredirection was called before a startredirection, perhaps you have unbalanced tags. Some debugging information:".join ":",caller);
1.328     albertel  902: 	return '';
                    903:     }
                    904:     $Apache::lonxml::redirection--;
                    905:     if (!$Apache::lonxml::redirection) {
                    906: 	$Apache::lonxml::metamode=$metamode_was;
                    907:     }
                    908:     pop @Apache::lonxml::outputstack;
1.97      albertel  909: }
1.459     albertel  910: sub in_redirection {
                    911:     return ($Apache::lonxml::redirection > 0)
                    912: }
1.97      albertel  913: 
                    914: sub end_tag {
                    915:   my ($tagstack,$parstack,$token)=@_;
                    916:   pop(@$tagstack);
                    917:   pop(@$parstack);
                    918:   &decreasedepth($token);
1.55      albertel  919: }
                    920: 
1.17      albertel  921: sub initdepth {
                    922:   @Apache::lonxml::depthcounter=();
1.439     albertel  923:   undef($Apache::lonxml::last_depth_count);
1.17      albertel  924: }
                    925: 
1.438     albertel  926: 
1.339     albertel  927: my @timers;
                    928: my $lasttime;
1.438     albertel  929: # @Apache::lonxml::depthcounter -> count of tags that exist so
                    930: #                                  far at each level
1.439     albertel  931: # $Apache::lonxml::last_depth_count -> when ascending, need to
                    932: # remember the count for the level below the current level (for
                    933: # example going from 1_2 -> 1 -> 1_3 need to remember the 2 )
1.438     albertel  934: 
1.17      albertel  935: sub increasedepth {
1.19      albertel  936:   my ($token) = @_;
1.439     albertel  937:   push(@Apache::lonxml::depthcounter,$Apache::lonxml::last_depth_count+1);
                    938:   undef($Apache::lonxml::last_depth_count);
1.340     albertel  939:   my $time;
                    940:   if ($Apache::lonxml::debug eq "1") {
                    941:       push(@timers,[&gettimeofday()]);
                    942:       $time=&tv_interval($lasttime);
                    943:       $lasttime=[&gettimeofday()];
                    944:   }
1.439     albertel  945:   my $spacing='  'x($#Apache::lonxml::depthcounter);
1.438     albertel  946:   $Apache::lonxml::curdepth=join('_',@Apache::lonxml::depthcounter);
1.439     albertel  947: #  &Apache::lonxml::debug("s$spacing$Apache::lonxml::depth : $Apache::lonxml::olddepth : $Apache::lonxml::curdepth : $token->[1] : $time");
1.54      albertel  948: #print "<br />s $Apache::lonxml::depth : $Apache::lonxml::olddepth : $curdepth : $token->[1]\n";
1.17      albertel  949: }
                    950: 
                    951: sub decreasedepth {
1.19      albertel  952:   my ($token) = @_;
1.439     albertel  953:   if (  $#Apache::lonxml::depthcounter == -1) {
                    954:       &Apache::lonxml::warning(&mt("Missing tags, unable to properly run file."));
1.43      albertel  955:   }
1.439     albertel  956:   $Apache::lonxml::last_depth_count = pop(@Apache::lonxml::depthcounter);
                    957: 
1.340     albertel  958:   my ($timer,$time);
                    959:   if ($Apache::lonxml::debug eq "1") {
                    960:       $timer=pop(@timers);
                    961:       $time=&tv_interval($lasttime);
                    962:       $lasttime=[&gettimeofday()];
                    963:   }
1.439     albertel  964:   my $spacing='  'x($#Apache::lonxml::depthcounter);
                    965:   $Apache::lonxml::curdepth = join('_',@Apache::lonxml::depthcounter);
                    966: #  &Apache::lonxml::debug("e$spacing$Apache::lonxml::depth : $Apache::lonxml::olddepth : $Apache::lonxml::curdepth : $token->[1] : $time : ".&tv_interval($timer));
1.54      albertel  967: #print "<br />e $Apache::lonxml::depth : $Apache::lonxml::olddepth : $token->[1] : $curdepth\n";
1.1       sakharuk  968: }
1.19      albertel  969: 
1.399     albertel  970: sub get_id {
                    971:     my ($parstack,$safeeval)=@_;
                    972:     my $id= &Apache::lonxml::get_param('id',$parstack,$safeeval);
1.449     albertel  973:     if ($env{'request.state'} eq 'construct' && $id =~ /([._]|[^\w\d\s[:punct:]])/) {
1.498     bisitz    974: 	&error(&mt('ID [_1] contains invalid characters. IDs are only allowed to contain letters, numbers, spaces and -','"<tt>'.$id.'</tt>"'));
1.399     albertel  975:     }
                    976:     if ($id =~ /^\s*$/) { $id = $Apache::lonxml::curdepth; }
                    977:     return $id;
                    978: }
                    979: 
1.180     albertel  980: sub get_all_text_unbalanced {
1.190     albertel  981: #there is a copy of this in lonpublisher.pm
1.326     albertel  982:     my($tag,$pars)= @_;
                    983:     my $token;
                    984:     my $result='';
                    985:     $tag='<'.$tag.'>';
                    986:     while ($token = $$pars[-1]->get_token) {
                    987: 	if (($token->[0] eq 'T')||($token->[0] eq 'C')||($token->[0] eq 'D')) {
1.386     albertel  988: 	    if ($token->[0] eq 'T' && $token->[2]) {
1.382     albertel  989: 		$result.='<![CDATA['.$token->[1].']]>';
                    990: 	    } else {
                    991: 		$result.=$token->[1];
                    992: 	    }
1.326     albertel  993: 	} elsif ($token->[0] eq 'PI') {
                    994: 	    $result.=$token->[2];
                    995: 	} elsif ($token->[0] eq 'S') {
                    996: 	    $result.=$token->[4];
                    997: 	} elsif ($token->[0] eq 'E')  {
                    998: 	    $result.=$token->[2];
                    999: 	}
                   1000: 	if ($result =~ /\Q$tag\E/is) {
                   1001: 	    ($result,my $redo)=$result =~ /(.*)\Q$tag\E(.*)/is;
                   1002: 	    #&Apache::lonxml::debug('Got a winner with leftovers ::'.$2);
                   1003: 	    #&Apache::lonxml::debug('Result is :'.$1);
                   1004: 	    $redo=$tag.$redo;
                   1005: 	    &Apache::lonxml::newparser($pars,\$redo);
                   1006: 	    last;
                   1007: 	}
                   1008:     }
                   1009:     return $result
1.462     foxr     1010: 
1.204     albertel 1011: }
                   1012: 
1.462     foxr     1013: #########################################################################
                   1014: #                                                                       #
                   1015: #           bubble line counter management                              #
                   1016: #                                                                       #
                   1017: #########################################################################
                   1018: 
1.447     albertel 1019: =pod
                   1020: 
                   1021: For bubble grading mode and exam bubble printing mode, the tracking of
                   1022: the current 'bubble line number' is stored in the %env element
                   1023: 'form.counter', and is modifed and handled by the following routines.
                   1024: 
                   1025: The value of it is stored in $Apache:lonxml::counter when live and
                   1026: stored back to env after done.
                   1027: 
1.522     raeburn  1028: =item &increment_counter($increment, $part_response);
1.447     albertel 1029: 
                   1030: Increments the internal counter environment variable a specified amount
                   1031: 
                   1032: Optional Arguments:
                   1033:   $increment - amount to increment by (defaults to 1)
1.462     foxr     1034:                Also 1 if the value is negative or zero.
1.467     foxr     1035:   $part_response - A concatenation of the part and response id
                   1036:                    identifying exactly what is being 'answered'.
                   1037: 
1.447     albertel 1038: 
                   1039: =cut
                   1040: 
1.204     albertel 1041: sub increment_counter {
1.467     foxr     1042:     my ($increment, $part_response) = @_;
1.481     raeburn  1043:     if ($env{'form.grade_noincrement'}) { return; }
1.462     foxr     1044:     if (!defined($increment) || $increment le 0) {
                   1045: 	$increment = 1;
                   1046:     }
                   1047:     $Apache::lonxml::counter += $increment;
                   1048: 
1.466     foxr     1049:     # If the caller supplied the response_id parameter, 
1.462     foxr     1050:     # Maintain its counter.. creating if necessary.
                   1051: 
1.470     albertel 1052:     if (defined($part_response)) {
1.467     foxr     1053: 	if (!defined($Apache::lonxml::counters_per_part{$part_response})) {
                   1054: 	    $Apache::lonxml::counters_per_part{$part_response} = 0;
1.462     foxr     1055: 	}
1.467     foxr     1056: 	$Apache::lonxml::counters_per_part{$part_response} += $increment;
                   1057: 	my $new_value = $Apache::lonxml::counters_per_part{$part_response};
1.247     albertel 1058:     }
1.462     foxr     1059: 	
1.289     sakharuk 1060:     $Apache::lonxml::counter_changed=1;
1.204     albertel 1061: }
                   1062: 
1.447     albertel 1063: =pod
                   1064: 
1.461     foxr     1065: =item &init_counter($increment);
1.447     albertel 1066: 
                   1067: Initialize the internal counter environment variable
                   1068: 
                   1069: =cut
                   1070: 
1.204     albertel 1071: sub init_counter {
1.391     albertel 1072:     if ($env{'request.state'} eq 'construct') {
                   1073: 	$Apache::lonxml::counter=1;
                   1074: 	$Apache::lonxml::counter_changed=1;
                   1075:     } elsif (defined($env{'form.counter'})) {
1.372     albertel 1076: 	$Apache::lonxml::counter=$env{'form.counter'};
1.247     albertel 1077: 	$Apache::lonxml::counter_changed=0;
1.237     sakharuk 1078:     } else {
1.204     albertel 1079: 	$Apache::lonxml::counter=1;
1.247     albertel 1080: 	$Apache::lonxml::counter_changed=1;
1.204     albertel 1081:     }
                   1082: }
                   1083: 
                   1084: sub store_counter {
1.474     raeburn  1085:     &Apache::lonnet::appenv({'form.counter' => $Apache::lonxml::counter});
1.401     albertel 1086:     $Apache::lonxml::counter_changed=0;
1.204     albertel 1087:     return '';
1.180     albertel 1088: }
                   1089: 
1.398     albertel 1090: {
                   1091:     my $state;
                   1092:     sub clear_problem_counter {
                   1093: 	undef($state);
                   1094: 	&Apache::lonnet::delenv('form.counter');
                   1095: 	&Apache::lonxml::init_counter();
                   1096: 	&Apache::lonxml::store_counter();
                   1097:     }
                   1098: 
                   1099:     sub remember_problem_counter {
1.422     albertel 1100: 	&Apache::lonnet::transfer_profile_to_env(undef,undef,1);
1.398     albertel 1101: 	$state = $env{'form.counter'};
                   1102:     }
                   1103: 
                   1104:     sub restore_problem_counter {
                   1105: 	if (defined($state)) {
1.474     raeburn  1106: 	    &Apache::lonnet::appenv({'form.counter' => $state});
1.398     albertel 1107: 	}
                   1108:     }
1.401     albertel 1109:     sub get_problem_counter {
                   1110: 	if ($Apache::lonxml::counter_changed) { &store_counter() }
1.422     albertel 1111: 	&Apache::lonnet::transfer_profile_to_env(undef,undef,1);
1.401     albertel 1112: 	return $env{'form.counter'};
                   1113:     }
1.398     albertel 1114: }
                   1115: 
1.462     foxr     1116: =pod
                   1117: 
1.468     albertel 1118: =item  bubble_lines_for_part(part_response)
1.462     foxr     1119: 
                   1120: Returns the number of lines required to get a response for
1.467     foxr     1121: $part_response (this is just $Apache::lonxml::counters_per_part{$part_response}
1.462     foxr     1122: 
                   1123: =cut
                   1124: 
                   1125: sub bubble_lines_for_part {
1.467     foxr     1126:     my ($part_response) = @_;
1.462     foxr     1127: 
1.467     foxr     1128:     if (!defined($Apache::lonxml::counters_per_part{$part_response})) {
1.462     foxr     1129: 	return 0;
                   1130:     } else {
1.467     foxr     1131: 	return $Apache::lonxml::counters_per_part{$part_response};
1.462     foxr     1132:     }
                   1133: }
                   1134: 
                   1135: =pod
                   1136: 
                   1137: =item clear_bubble_lines_for_part
                   1138: 
                   1139: Clears the hash of bubble lines per part.  If a caller
                   1140: needs to analyze several resources this should be called between
                   1141: resources to reset the hash for each problem being analyzed.
                   1142: 
                   1143: =cut
                   1144: 
                   1145: sub clear_bubble_lines_for_part {
                   1146:     undef(%Apache::lonxml::counters_per_part);
                   1147: }
                   1148: 
                   1149: =pod
                   1150: 
1.468     albertel 1151: =item set_bubble_lines(part_response, value)
1.462     foxr     1152: 
                   1153: If there is a problem part, that for whatever reason
                   1154: requires bubble lines that are not
                   1155: the same as the counter increment, it can call this sub during
                   1156: analysis to set its hash value explicitly.
                   1157: 
                   1158: =cut
                   1159: 
                   1160: sub set_bubble_lines {
1.467     foxr     1161:     my ($part_response, $value) = @_;
1.462     foxr     1162: 
1.467     foxr     1163:     $Apache::lonxml::counters_per_part{$part_response} = $value;
1.462     foxr     1164: }
                   1165: 
                   1166: =pod
                   1167: 
                   1168: =item get_bubble_line_hash
                   1169: 
                   1170: Returns the current bubble line hash.  This is assumed to 
                   1171: be small so we return a copy
                   1172: 
                   1173: 
                   1174: =cut
                   1175: 
                   1176: sub get_bubble_line_hash {
                   1177:     return %Apache::lonxml::counters_per_part;
                   1178: }
                   1179: 
                   1180: 
                   1181: #--------------------------------------------------
                   1182: 
1.19      albertel 1183: sub get_all_text {
1.270     albertel 1184:     my($tag,$pars,$style)= @_;
                   1185:     my $gotfullstack=1;
                   1186:     if (ref($pars) ne 'ARRAY') {
                   1187: 	$gotfullstack=0;
                   1188: 	$pars=[$pars];
                   1189:     }
                   1190:     if (ref($style) ne 'HASH') {
                   1191: 	$style={};
                   1192:     }
                   1193:     my $depth=0;
                   1194:     my $token;
                   1195:     my $result='';
                   1196:     if ( $tag =~ m:^/: ) { 
                   1197: 	my $tag=substr($tag,1); 
                   1198: 	#&Apache::lonxml::debug("have:$tag:");
                   1199: 	my $top_empty=0;
                   1200: 	while (($depth >=0) && ($#$pars > -1) && (!$top_empty)) {
                   1201: 	    while (($depth >=0) && ($token = $$pars[-1]->get_token)) {
                   1202: 		#&Apache::lonxml::debug("e token:$token->[0]:$depth:$token->[1]:".$#$pars.":".$#Apache::lonxml::pwd);
                   1203: 		if (($token->[0] eq 'T')||($token->[0] eq 'C')||($token->[0] eq 'D')) {
1.382     albertel 1204: 		    if ($token->[2]) {
                   1205: 			$result.='<![CDATA['.$token->[1].']]>';
                   1206: 		    } else {
                   1207: 			$result.=$token->[1];
                   1208: 		    }
1.270     albertel 1209: 		} elsif ($token->[0] eq 'PI') {
                   1210: 		    $result.=$token->[2];
                   1211: 		} elsif ($token->[0] eq 'S') {
1.316     albertel 1212: 		    if ($token->[1] =~ /^\Q$tag\E$/i) { $depth++; }
                   1213: 		    if ($token->[1] =~ /^LONCAPA_INTERNAL_TURN_STYLE_ON$/) { $Apache::lonxml::usestyle=1; }
                   1214: 		    if ($token->[1] =~ /^LONCAPA_INTERNAL_TURN_STYLE_OFF$/) { $Apache::lonxml::usestyle=0; }
1.270     albertel 1215: 		    $result.=$token->[4];
                   1216: 		} elsif ($token->[0] eq 'E')  {
1.316     albertel 1217: 		    if ( $token->[1] =~ /^\Q$tag\E$/i) { $depth--; }
1.270     albertel 1218: 		    #skip sending back the last end tag
1.283     albertel 1219: 		    if ($depth == 0 && exists($$style{'/'.$token->[1]}) && $Apache::lonxml::usestyle) {
1.270     albertel 1220: 			my $string=
                   1221: 			    '<LONCAPA_INTERNAL_TURN_STYLE_OFF end="yes" />'.
                   1222: 				$$style{'/'.$token->[1]}.
                   1223: 				    $token->[2].
                   1224: 					'<LONCAPA_INTERNAL_TURN_STYLE_ON />';
                   1225: 			&Apache::lonxml::newparser($pars,\$string);
                   1226: 			#&Apache::lonxml::debug("reParsing $string");
                   1227: 			next;
                   1228: 		    }
                   1229: 		    if ($depth > -1) {
                   1230: 			$result.=$token->[2];
                   1231: 		    } else {
                   1232: 			$$pars[-1]->unget_token($token);
                   1233: 		    }
                   1234: 		}
                   1235: 	    }
                   1236: 	    if (($depth >=0) && ($#$pars == 0) ) { $top_empty=1; }
                   1237: 	    if (($depth >=0) && ($#$pars > 0) ) {
                   1238: 		pop(@$pars);
                   1239: 		pop(@Apache::lonxml::pwd);
                   1240: 	    }
                   1241: 	}
                   1242: 	if ($top_empty && $depth >= 0) {
                   1243: 	    #never found the end tag ran out of text, throw error send back blank
                   1244: 	    &error('Never found end tag for &lt;'.$tag.
                   1245: 		   '&gt; current string <pre>'.
1.314     albertel 1246: 		   &HTML::Entities::encode($result,'<>&"').
1.270     albertel 1247: 		   '</pre>');
                   1248: 	    if ($gotfullstack) {
                   1249: 		my $newstring='</'.$tag.'>'.$result;
                   1250: 		&Apache::lonxml::newparser($pars,\$newstring);
                   1251: 	    }
                   1252: 	    $result='';
                   1253: 	}
                   1254:     } else {
                   1255: 	while ($#$pars > -1) {
                   1256: 	    while ($token = $$pars[-1]->get_token) {
                   1257: 		#&Apache::lonxml::debug("s token:$token->[0]:$depth:$token->[1]");
                   1258: 		if (($token->[0] eq 'T')||($token->[0] eq 'C')||
                   1259: 		    ($token->[0] eq 'D')) {
1.382     albertel 1260: 		    if ($token->[2]) {
                   1261: 			$result.='<![CDATA['.$token->[1].']]>';
                   1262: 		    } else {
                   1263: 			$result.=$token->[1];
                   1264: 		    }
1.270     albertel 1265: 		} elsif ($token->[0] eq 'PI') {
                   1266: 		    $result.=$token->[2];
                   1267: 		} elsif ($token->[0] eq 'S') {
1.316     albertel 1268: 		    if ( $token->[1] =~ /^\Q$tag\E$/i) {
1.270     albertel 1269: 			$$pars[-1]->unget_token($token); last;
                   1270: 		    } else {
                   1271: 			$result.=$token->[4];
                   1272: 		    }
1.316     albertel 1273: 		    if ($token->[1] =~ /^LONCAPA_INTERNAL_TURN_STYLE_ON$/) { $Apache::lonxml::usestyle=1; }
                   1274: 		    if ($token->[1] =~ /^LONCAPA_INTERNAL_TURN_STYLE_OFF$/) { $Apache::lonxml::usestyle=0; }
1.270     albertel 1275: 		} elsif ($token->[0] eq 'E')  {
                   1276: 		    $result.=$token->[2];
                   1277: 		}
                   1278: 	    }
                   1279: 	    if (($#$pars > 0) ) {
                   1280: 		pop(@$pars);
                   1281: 		pop(@Apache::lonxml::pwd);
                   1282: 	    } else { last; }
                   1283: 	}
                   1284:     }
                   1285:     #&Apache::lonxml::debug("Exit:$result:");
                   1286:     return $result
1.19      albertel 1287: }
                   1288: 
1.23      albertel 1289: sub newparser {
                   1290:   my ($parser,$contentref,$dir) = @_;
1.167     albertel 1291:   push (@$parser,HTML::LCParser->new($contentref));
1.365     albertel 1292:   $$parser[-1]->xml_mode(1);
                   1293:   $$parser[-1]->marked_sections(1);
1.23      albertel 1294:   if ( $dir eq '' ) {
                   1295:     push (@Apache::lonxml::pwd, $Apache::lonxml::pwd[$#Apache::lonxml::pwd]);
                   1296:   } else {
                   1297:     push (@Apache::lonxml::pwd, $dir);
                   1298:   } 
                   1299: }
1.1       sakharuk 1300: 
1.8       albertel 1301: sub parstring {
1.417     albertel 1302:     my ($token) = @_;
                   1303:     my (@vars,@values);
                   1304:     foreach my $attr (@{$token->[3]}) {
                   1305: 	if ($attr!~/\W/) {
                   1306: 	    my $val=$token->[2]->{$attr};
                   1307: 	    $val =~ s/([\%\@\\\"\'])/\\$1/g;
                   1308: 	    $val =~ s/(\$[^\{a-zA-Z_])/\\$1/g;
                   1309: 	    $val =~ s/(\$)$/\\$1/;
                   1310: 	    #if ($val =~ m/^[\%\@]/) { $val="\\".$val; }
                   1311: 	    push(@vars,"\$$attr");
                   1312: 	    push(@values,"\"$val\"");
                   1313: 	}
                   1314:     }
                   1315:     my $var_init = 
                   1316: 	(@vars) ? 'my ('.join(',',@vars).') = ('.join(',',@values).');'
                   1317: 	        : '';
                   1318:     return $var_init;
1.8       albertel 1319: }
1.22      albertel 1320: 
1.384     albertel 1321: sub extlink {
                   1322:     my ($res,$exact)=@_;
                   1323:     if (!$exact) {
                   1324: 	$res=&Apache::lonnet::hreflocation($Apache::lonxml::pwd[-1],$res);
                   1325:     }
                   1326:     push(@Apache::lonxml::extlinks,$res)	 
                   1327: }
                   1328: 
1.34      www      1329: sub writeallows {
1.126     www      1330:     unless ($#extlinks>=0) { return; }
1.377     albertel 1331:     my $thisurl = &Apache::lonnet::clutter(shift);
1.372     albertel 1332:     if ($env{'httpref.'.$thisurl}) {
                   1333: 	$thisurl=$env{'httpref.'.$thisurl};
1.111     www      1334:     }
1.34      www      1335:     my $thisdir=$thisurl;
                   1336:     $thisdir=~s/\/[^\/]+$//;
                   1337:     my %httpref=();
1.142     albertel 1338:     foreach (@extlinks) {
1.34      www      1339:        $httpref{'httpref.'.
1.444     albertel 1340:  	        &Apache::lonnet::hreflocation($thisdir,&unescape($_))}=$thisurl;
1.142     albertel 1341:     }
1.126     www      1342:     @extlinks=();
1.474     raeburn  1343:     &Apache::lonnet::appenv(\%httpref);
1.34      www      1344: }
                   1345: 
1.281     albertel 1346: sub register_ssi {
                   1347:     my ($url,%form)=@_;
                   1348:     push (@Apache::lonxml::ssi_info,{'url'=>$url,'form'=>\%form});
                   1349:     return '';
                   1350: }
                   1351: 
                   1352: sub do_registered_ssi {
                   1353:     foreach my $info (@Apache::lonxml::ssi_info) {
                   1354: 	my %form=%{ $info->{'form'}};
                   1355: 	my $url=$info->{'url'};
                   1356: 	&Apache::lonnet::ssi($url,%form);
                   1357:     }
                   1358: }
1.448     albertel 1359: 
                   1360: sub add_script_result {
                   1361:     my ($display) = @_;
                   1362:     push(@script_var_displays, $display);
                   1363: }
                   1364: 
1.66      www      1365: #
                   1366: # Afterburner handles anchors, highlights and links
                   1367: #
                   1368: sub afterburn {
                   1369:     my $result=shift;
1.154     albertel 1370:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
                   1371: 					    ['highlight','anchor','link']);
1.372     albertel 1372:     if ($env{'form.highlight'}) {
                   1373:        foreach (split(/\,/,$env{'form.highlight'})) {
1.66      www      1374:            my $anchorname=$_;
                   1375: 	   my $matchthis=$anchorname;
                   1376:            $matchthis=~s/\_+/\\s\+/g;
1.317     albertel 1377:            $result=~s/(\Q$matchthis\E)/\<font color=\"red\"\>$1\<\/font\>/gs;
1.142     albertel 1378:        }
1.66      www      1379:     }
1.372     albertel 1380:     if ($env{'form.link'}) {
                   1381:        foreach (split(/\,/,$env{'form.link'})) {
1.66      www      1382:            my ($anchorname,$linkurl)=split(/\>/,$_);
                   1383: 	   my $matchthis=$anchorname;
                   1384:            $matchthis=~s/\_+/\\s\+/g;
1.317     albertel 1385:            $result=~s/(\Q$matchthis\E)/\<a href=\"$linkurl\"\>$1\<\/a\>/gs;
1.142     albertel 1386:        }
1.66      www      1387:     }
1.372     albertel 1388:     if ($env{'form.anchor'}) {
                   1389:         my $anchorname=$env{'form.anchor'};
1.66      www      1390: 	my $matchthis=$anchorname;
                   1391:         $matchthis=~s/\_+/\\s\+/g;
1.317     albertel 1392:         $result=~s/(\Q$matchthis\E)/\<a name=\"$anchorname\"\>$1\<\/a\>/s;
1.66      www      1393:         $result.=(<<"ENDSCRIPT");
1.226     albertel 1394: <script type="text/javascript">
1.66      www      1395:     document.location.hash='$anchorname';
                   1396: </script>
                   1397: ENDSCRIPT
                   1398:     }
                   1399:     return $result;
                   1400: }
                   1401: 
1.79      www      1402: sub storefile {
                   1403:     my ($file,$contents)=@_;
1.290     albertel 1404:     &Apache::lonnet::correct_line_ends(\$contents);
1.79      www      1405:     if (my $fh=Apache::File->new('>'.$file)) {
                   1406: 	print $fh $contents;
                   1407:         $fh->close();
1.271     www      1408:         return 1;
1.147     albertel 1409:     } else {
1.482     bisitz   1410: 	&warning(&mt('Unable to save file [_1]','<tt>'.$file.'</tt>'));
1.271     www      1411: 	return 0;
1.79      www      1412:     }
                   1413: }
                   1414: 
1.151     albertel 1415: sub createnewhtml {
1.321     www      1416:     my $title=&mt('Title of document goes here');
                   1417:     my $body=&mt('Body of document goes here');
                   1418:     my $filecontents=(<<SIMPLECONTENT);
1.78      www      1419: <html>
                   1420: <head>
1.321     www      1421: <title>$title</title>
1.78      www      1422: </head>
                   1423: <body bgcolor="#FFFFFF">
1.321     www      1424: $body
1.78      www      1425: </body>
                   1426: </html>
                   1427: SIMPLECONTENT
1.321     www      1428:     return $filecontents;
1.151     albertel 1429: }
                   1430: 
1.274     albertel 1431: sub createnewsty {
                   1432:   my $filecontents=(<<SIMPLECONTENT);
                   1433: <definetag name="">
                   1434:     <render>
                   1435:        <web></web>
                   1436:        <tex></tex>
                   1437:     </render>
                   1438: </definetag>
                   1439: SIMPLECONTENT
                   1440:   return $filecontents;
                   1441: }
                   1442: 
1.493     raeburn  1443: sub createnewjs {
                   1444:     my $filecontents=(<<SIMPLECONTENT);
                   1445: <script type="text/javascript" language="Javascript">
                   1446: 
                   1447: </script>
                   1448: SIMPLECONTENT
                   1449:     return $filecontents;
                   1450: }
                   1451: 
1.472     www      1452: sub verify_html {
                   1453:     my ($filecontents)=@_;
1.516     raeburn  1454:     my ($is_html,$is_xml);
                   1455:     if ($filecontents =~/(?:\<|\&lt\;)\?xml[^\<]*\?(?:\>|\&gt\;)/is) {
                   1456:         $is_xml = 1;
1.518     raeburn  1457:     } elsif ($filecontents =~/(?:\<|\&lt\;)html(?:\s+[^\<]+|\s*)(?:\>|\&gt\;)/is) {
1.516     raeburn  1458:         $is_html = 1;
                   1459:     }
                   1460:     unless ($is_xml || $is_html) {
                   1461:         return &mt('File does not have [_1] or [_2] starting tag','&lt;html&gt;','&lt;?xml ?&gt;');
                   1462:     }
                   1463:     if ($is_html) {
                   1464:         if ($filecontents!~/(?:\<|\&lt\;)\/html(?:\>|\&gt\;)/is) {
                   1465:             return &mt('File does not have [_1] ending tag','&lt;html&gt;');
                   1466:         }
                   1467:         if ($filecontents!~/(?:\<|\&lt\;)(?:body|frameset)[^\<]*(?:\>|\&gt\;)/is) {
                   1468:             return &mt('File does not have [_1] or [_2] starting tag','&lt;body&gt;','&lt;frameset&gt;');
                   1469:         }
                   1470:         if ($filecontents!~/(?:\<|\&lt\;)\/(?:body|frameset)[^\<]*(?:\>|\&gt\;)/is) {
                   1471:             return &mt('File does not have [_1] or [_2] ending tag','&lt;body&gt;','&lt;frameset&gt;');
                   1472:         }
1.472     www      1473:     }
                   1474:     return '';
                   1475: }
1.147     albertel 1476: 
1.478     www      1477: sub renderingoptions {
                   1478:     my %langchoices=('' => '');
                   1479:     foreach (&Apache::loncommon::languageids()) {
                   1480:         if (&Apache::loncommon::supportedlanguagecode($_)) {
                   1481:             $langchoices{&Apache::loncommon::supportedlanguagecode($_)}
                   1482:                        = &Apache::loncommon::plainlanguagedescription($_);
                   1483:         }
                   1484:     }
1.500     raeburn  1485:     my $output;
                   1486:     unless ($env{'form.forceedit'}) {
1.504     bisitz   1487:        $output .=
                   1488:            '<span class="LC_nobreak">'.
1.500     raeburn  1489:            &mt('Language:').' '.
1.504     bisitz   1490:            &Apache::loncommon::select_form(
                   1491:                $env{'form.languages'},
                   1492:                'languages',
1.510     raeburn  1493:                {&Apache::lonlocal::texthash(%langchoices)}).
1.504     bisitz   1494:            '</span>';
1.500     raeburn  1495:     }
1.504     bisitz   1496:     $output .=
                   1497:      ' <span class="LC_nobreak">'.
1.479     bisitz   1498:        &mt('Math Rendering:').' '.
1.504     bisitz   1499:        &Apache::loncommon::select_form(
                   1500:            $env{'form.texengine'},
                   1501:            'texengine',
1.510     raeburn  1502:            {&Apache::lonlocal::texthash
1.504     bisitz   1503:                (''        => '',
                   1504:                 'tth'     => 'tth (TeX to HTML)',
1.526     dseaton  1505:                 'MathJax' => 'MathJax',
                   1506:   		'jsMath'  => 'jsMath',
1.510     raeburn  1507:                 'mimetex' => 'mimetex (Convert to Images)')}).
1.504     bisitz   1508:      '</span>';
1.500     raeburn  1509:     return $output;
1.478     www      1510: }
                   1511: 
1.151     albertel 1512: sub inserteditinfo {
1.543   ! raeburn  1513:       my ($filecontents,$filetype,$filename,$symb,$itemtitle,$folderpath,$uri,$action) = @_;
1.314     albertel 1514:       $filecontents = &HTML::Entities::encode($filecontents,'<>&"');
1.274     albertel 1515:       my $xml_help = '';
1.321     www      1516:       my $initialize='';
1.452     albertel 1517:       my $textarea_id = 'filecont';
1.530     raeburn  1518:       my ($dragmath_button,$deps_button);
1.452     albertel 1519:       my ($add_to_onload, $add_to_onresize);
1.456     albertel 1520:       $initialize=&Apache::lonhtmlcommon::spellheader();
1.514     raeburn  1521:       if (($filetype eq 'html') && (&Apache::lonhtmlcommon::htmlareabrowser())) {
1.463     albertel 1522: 	  my $lang = &Apache::lonhtmlcommon::htmlarea_lang();
1.512     raeburn  1523:           my %textarea_args = (
                   1524:                                 fullpage => 'true',
                   1525:                                 dragmath => 'math',
                   1526:                               );
1.514     raeburn  1527:           $initialize .= &Apache::lonhtmlcommon::htmlareaselectactive(\%textarea_args); 
                   1528:       }
                   1529:       $initialize .= (<<FULLPAGE);
1.321     www      1530: <script type="text/javascript">
1.514     raeburn  1531: // <![CDATA[
1.321     www      1532:     function initDocument() {
1.463     albertel 1533: 	resize_textarea('$textarea_id','LC_aftertextarea');
1.321     www      1534:     }
1.514     raeburn  1535: // ]]>
1.321     www      1536: </script>
                   1537: FULLPAGE
1.540     raeburn  1538:       my $textareaclass;
1.514     raeburn  1539:       if ($filetype eq 'html') {
1.539     raeburn  1540:           my $context;
                   1541:           if ($env{'request.course.id'}) {
                   1542:               my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   1543:               my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   1544:               if ($uri =~ m{^\Q/uploaded/$cdom/$cnum/portfolio/syllabus/\E}) {
                   1545:                   $context = 'syllabus';
                   1546:                   $deps_button = &Apache::lonhtmlcommon::dependencies_button()."\n";
                   1547:                   $initialize .=
                   1548:                       &Apache::lonhtmlcommon::dependencycheck_js(undef,&mt('Syllabus'),
                   1549:                                                                  $uri,undef,
                   1550:                                                                  "/public/$cdom/$cnum/syllabus").
                   1551:                       "\n";
1.540     raeburn  1552:                   if (&Apache::lonhtmlcommon::htmlareabrowser()) {
                   1553:                       $textareaclass = 'class="LC_richDefaultOn"';
                   1554:                   }
1.539     raeburn  1555:               }
                   1556:           }
                   1557:           unless ($context eq 'syllabus') {
                   1558:               if ($symb || $folderpath) {
                   1559:                   $deps_button = &Apache::lonhtmlcommon::dependencies_button()."\n";
                   1560:                   $initialize .= 
                   1561:                       &Apache::lonhtmlcommon::dependencycheck_js($symb,$itemtitle,
                   1562:                                                                  undef,$folderpath,$uri)."\n";
                   1563:               }
1.530     raeburn  1564:           }
1.514     raeburn  1565:           $dragmath_button = '<span id="math_filecont">'.&Apache::lonhtmlcommon::dragmath_button('filecont',1).'</span>';
                   1566:           $initialize .= "\n".&Apache::lonhtmlcommon::dragmath_js('EditMathPopup');
1.512     raeburn  1567:       }
1.456     albertel 1568:       $add_to_onload = 'initDocument();';
                   1569:       $add_to_onresize = "resize_textarea('$textarea_id','LC_aftertextarea');";
                   1570: 
                   1571:       if ($filetype eq 'html') {
1.321     www      1572: 	  $xml_help=&Apache::loncommon::helpLatexCheatsheet();
1.274     albertel 1573:       }
1.452     albertel 1574: 
1.254     albertel 1575:       my $titledisplay=&display_title();
1.426     banghart 1576:       my %lt=&Apache::lonlocal::texthash('st' => 'Save and Edit',
                   1577: 					 'vi' => 'Save and View',
1.427     banghart 1578: 					 'dv' => 'Discard Edits and View',
1.428     banghart 1579: 					 'un' => 'undo',
1.280     www      1580: 					 'ed' => 'Edit');
1.512     raeburn  1581:       my $spelllink = &Apache::lonhtmlcommon::spelllink('xmledit','filecont');
1.451     albertel 1582:       my $textarea_events = &Apache::edit::element_change_detection();
                   1583:       my $form_events     = &Apache::edit::form_change_detection();
1.491     raeburn  1584:       my $htmlerror;
                   1585:       if ($filetype eq 'html') {
                   1586:           $htmlerror=&verify_html($filecontents);
                   1587:           if ($htmlerror) {
                   1588:               $htmlerror='<span class="LC_error">'.$htmlerror.'</span>';
                   1589:           }
1.501     raeburn  1590:           if (&Apache::lonhtmlcommon::htmlareabrowser()) {
1.540     raeburn  1591:               unless ($textareaclass) {
                   1592:                   $textareaclass = 'class="LC_richDefaultOff"';
                   1593:               }
1.501     raeburn  1594:           }
1.472     www      1595:       }
1.78      www      1596:       my $editfooter=(<<ENDFOOTER);
1.321     www      1597: $initialize
1.78      www      1598: <a name="editsection" />
1.543   ! raeburn  1599: <form $form_events method="post" name="xmledit" action="$action">
1.470     albertel 1600:   <div class="LC_edit_problem_editxml_header">
                   1601:     <table class="LC_edit_problem_header_title"><tr><td>
                   1602:         $filename
                   1603:       </td><td align="right">
                   1604:         $xml_help
                   1605:       </td></tr>
                   1606:     </table>
                   1607:     <div class="LC_edit_problem_discards">
                   1608:       <input type="submit" name="discardview" accesskey="d" value="$lt{'dv'}" />
                   1609:       <input type="submit" name="Undo" accesskey="u" value="$lt{'un'}" />
1.530     raeburn  1610:       $htmlerror $deps_button $dragmath_button
1.470     albertel 1611:     </div>
                   1612:     <div class="LC_edit_problem_saves">
                   1613:       <input type="submit" name="savethisfile" accesskey="s" value="$lt{'st'}" />
                   1614:       <input type="submit" name="viewmode" accesskey="v" value="$lt{'vi'}" />
                   1615:     </div>
                   1616:   </div>
1.513     raeburn  1617:   <textarea $textarea_events style="width:100%" cols="80" rows="44" name="filecont" id="filecont" $textareaclass>$filecontents</textarea><br />$spelllink
1.470     albertel 1618:   <div id="LC_aftertextarea">
                   1619:     <br />
                   1620:     $titledisplay
                   1621:   </div>
1.78      www      1622: </form>
                   1623: ENDFOOTER
1.452     albertel 1624:       return ($editfooter,$add_to_onload,$add_to_onresize);;
1.78      www      1625: }
                   1626: 
1.152     albertel 1627: sub get_target {
1.372     albertel 1628:   my $viewgrades=&Apache::lonnet::allowed('vgr',$env{'request.course.id'});
                   1629:   if ( $env{'request.state'} eq 'published') {
                   1630:     if ( defined($env{'form.grade_target'})
1.152     albertel 1631: 	 && ($viewgrades == 'F' )) {
1.372     albertel 1632:       return ($env{'form.grade_target'});
                   1633:     } elsif (defined($env{'form.grade_target'})) {
                   1634:       if (($env{'form.grade_target'} eq 'web') ||
                   1635: 	  ($env{'form.grade_target'} eq 'tex') ) {
                   1636: 	return $env{'form.grade_target'}
1.153     albertel 1637:       } else {
                   1638: 	return 'web';
                   1639:       }
1.152     albertel 1640:     } else {
                   1641:       return 'web';
                   1642:     }
1.372     albertel 1643:   } elsif ($env{'request.state'} eq 'construct') {
                   1644:     if ( defined($env{'form.grade_target'})) {
                   1645:       return ($env{'form.grade_target'});
1.152     albertel 1646:     } else {
                   1647:       return 'web';
                   1648:     }
                   1649:   } else {
                   1650:     return 'web';
                   1651:   }
                   1652: }
                   1653: 
1.24      sakharuk 1654: sub handler {
1.255     sakharuk 1655:     my $request=shift;
1.493     raeburn  1656: 
1.255     sakharuk 1657:     my $target=&get_target();
1.372     albertel 1658:     $Apache::lonxml::debug=$env{'user.debug'};
1.255     sakharuk 1659:     
1.364     albertel 1660:     &Apache::loncommon::content_type($request,'text/html');
1.255     sakharuk 1661:     &Apache::loncommon::no_cache($request);
1.372     albertel 1662:     if ($env{'request.state'} eq 'published') {
1.363     albertel 1663: 	$request->set_last_modified(&Apache::lonnet::metadata($request->uri,
                   1664: 							      'lastrevisiondate'));
                   1665:     }
1.499     raeburn  1666:     # Embedded Flash movies from Camtasia served from https will not display in IE
                   1667:     #   if XML config file has expired from cache.    
                   1668:     if ($ENV{'SERVER_PORT'} == 443) {
                   1669:         if ($request->uri =~ /\.xml$/) {
                   1670:             my ($httpbrowser,$clientbrowser) =
                   1671:                 &Apache::loncommon::decode_user_agent($request);
                   1672:             if ($clientbrowser =~ /^explorer$/i) {
                   1673:                 delete $request->headers_out->{'Cache-control'};
                   1674:                 delete $request->headers_out->{'Pragma'};
                   1675:                 my $expiration = time + 60;
                   1676:                 my $date=strftime("%a, %d %b %Y %H:%M:%S GMT",gmtime($expiration));
                   1677:                 $request->headers_out->set("Expires" => $date);
                   1678:             }
                   1679:         }
                   1680:     }
1.255     sakharuk 1681:     $request->send_http_header;
                   1682:     
                   1683:     return OK if $request->header_only;
1.68      www      1684: 
                   1685: 
1.255     sakharuk 1686:     my $file=&Apache::lonnet::filelocation("",$request->uri);
1.502     raeburn  1687:     my ($filetype,$breadcrumbtext);
                   1688:     if ($file =~ /\.(sty|css|js|txt|tex)$/) {
1.493     raeburn  1689: 	$filetype=$1;
1.274     albertel 1690:     } else {
                   1691: 	$filetype='html';
1.537     raeburn  1692:     }
                   1693:     unless ($env{'request.uri'}) {
1.536     raeburn  1694:         $env{'request.uri'}=$request->uri;
1.537     raeburn  1695:         &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
                   1696:                                                 ['todocs']);
1.274     albertel 1697:     }
1.540     raeburn  1698:     my ($cdom,$cnum);
                   1699:     if ($env{'request.course.id'}) {
                   1700:         $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   1701:         $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   1702:         if ($filetype eq 'html') {
                   1703:             if ($request->uri =~ m{^\Q/uploaded/$cdom/$cnum/portfolio/syllabus/\E.+$}) {
                   1704:                 if (&Apache::lonnet::allowed('mdc',$env{'request.course.id'})) {
                   1705:                     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
                   1706:                                                             ['editmode']);
                   1707:                 }
                   1708:             }
                   1709:         }
                   1710:     }
1.502     raeburn  1711:     if ($filetype eq 'sty') {
                   1712:         $breadcrumbtext = 'Style File Editor';
                   1713:     } elsif ($filetype eq 'js') {
                   1714:         $breadcrumbtext = 'Javascript Editor';
                   1715:     } elsif ($filetype eq 'css') {
                   1716:         $breadcrumbtext = 'CSS Editor';
                   1717:     } elsif ($filetype eq 'txt') {
                   1718:         $breadcrumbtext = 'Text Editor';
                   1719:     } elsif ($filetype eq 'tex') {
                   1720:         $breadcrumbtext = 'TeX Editor';
                   1721:     } else {
                   1722:         $breadcrumbtext = 'HTML Editor';
                   1723:     }
1.493     raeburn  1724: 
1.78      www      1725: #
                   1726: # Edit action? Save file.
                   1727: #
1.428     banghart 1728:     if (!($env{'request.state'} eq 'published')) {
                   1729: 	if ($env{'form.savethisfile'} || $env{'form.viewmode'} || $env{'form.Undo'}) {
1.429     albertel 1730: 	    my $html_file=&Apache::lonnet::getfile($file);
                   1731: 	    my $error = &Apache::lonhomework::handle_save_or_undo($request, \$html_file, \$env{'form.filecont'});
1.472     www      1732:             if ($env{'form.savethisfile'}) {
                   1733:                 $env{'form.editmode'}='Edit'; #force edit mode
                   1734:             }
1.255     sakharuk 1735: 	}
                   1736:     }
                   1737:     my %mystyle;
                   1738:     my $result = '';
                   1739:     my $filecontents=&Apache::lonnet::getfile($file);
                   1740:     if ($filecontents eq -1) {
1.402     albertel 1741: 	my $start_page=&Apache::loncommon::start_page('File Error');
1.412     albertel 1742: 	my $end_page=&Apache::loncommon::end_page();
1.495     bisitz   1743:         my $errormsg='<p class="LC_error">'
                   1744:                     .&mt('File not found: [_1]'
                   1745:                         ,'<span class="LC_filename">'.$file.'</span>')
                   1746:                     .'</p>';
1.255     sakharuk 1747: 	$result=(<<ENDNOTFOUND);
1.402     albertel 1748: $start_page
1.495     bisitz   1749: $errormsg
1.402     albertel 1750: $end_page
1.78      www      1751: ENDNOTFOUND
1.343     albertel 1752:         $filecontents='';
1.372     albertel 1753: 	if ($env{'request.state'} ne 'published') {
1.274     albertel 1754: 	    if ($filetype eq 'sty') {
                   1755: 		$filecontents=&createnewsty();
1.493     raeburn  1756:             } elsif ($filetype eq 'js') {
                   1757:                 $filecontents=&createnewjs();
1.502     raeburn  1758:             } elsif ($filetype ne 'css' && $filetype ne 'txt' && $filetype ne 'tex') {
1.274     albertel 1759: 		$filecontents=&createnewhtml();
                   1760: 	    }
1.372     albertel 1761: 	    $env{'form.editmode'}='Edit'; #force edit mode
1.255     sakharuk 1762: 	}
                   1763:     } else {
1.372     albertel 1764: 	unless ($env{'request.state'} eq 'published') {
1.343     albertel 1765: 	    if ($filecontents=~/BEGIN LON-CAPA Internal/) {
1.381     www      1766: 		&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.'));
1.343     albertel 1767: 	    }
1.264     www      1768: #
                   1769: # we are in construction space, see if edit mode forced
1.385     albertel 1770:             &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
                   1771: 						    ['editmode']);
1.255     sakharuk 1772: 	}
1.427     banghart 1773: 	if (!$env{'form.editmode'} || $env{'form.viewmode'} || $env{'form.discardview'}) {
1.493     raeburn  1774:             if ($filetype eq 'html' || $filetype eq 'sty') {
                   1775: 	        &Apache::structuretags::reset_problem_globals();
                   1776: 	        $result = &Apache::lonxml::xmlparse($request,$target,
                   1777:                                                     $filecontents,'',%mystyle);
1.455     albertel 1778: 	    # .html files may contain <problem> or <Task> need to clean
                   1779: 	    # up if it did
1.493     raeburn  1780: 	        &Apache::structuretags::reset_problem_globals();
                   1781: 	        &Apache::lonhomework::finished_parsing();
1.502     raeburn  1782:             } elsif ($filetype eq 'tex') {
1.503     raeburn  1783:                 $result = &Apache::lontexconvert::converted(\$filecontents,
                   1784:                               $env{'form.texengine'});
                   1785:                 if ($env{'form.return_only_error_and_warning_counts'}) {
                   1786:                     $result = "$errorcount:$warningcount";
                   1787:                 }
1.493     raeburn  1788:             } else {
                   1789:                 $result = $filecontents;
                   1790:             }
1.385     albertel 1791: 	    &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
                   1792: 						    ['rawmode']);
1.395     albertel 1793: 	    if ($env{'form.rawmode'}) { $result = $filecontents; }
1.503     raeburn  1794:             if (($filetype ne 'html') && 
                   1795:                 (!$env{'form.return_only_error_and_warning_counts'})) {
1.502     raeburn  1796:                 my $nochgview = 1;
1.495     bisitz   1797:                 my $controls = '';
                   1798:                     if ($env{'request.state'} eq 'construct') {
                   1799:                         $controls = &Apache::loncommon::head_subbox(
                   1800:                                         &Apache::loncommon::CSTR_pageheader()
                   1801:                                        .&Apache::londefdef::edit_controls($nochgview));
                   1802:                     }
1.502     raeburn  1803:                 if ($filetype ne 'sty' && $filetype ne 'tex') {
1.493     raeburn  1804:                     $result =~ s/</&lt;/g;
                   1805:                     $result =~ s/>/&gt;/g;
                   1806:                     $result = '<table class="LC_sty_begin">'.
                   1807:                               '<tr><td><b><pre>'.$result.
                   1808:                               '</pre></b></td></tr></table>';
                   1809:                 }
1.506     droeschl 1810:                 my $brcrum;
                   1811:                 if ($env{'request.state'} eq 'construct') {
1.523     raeburn  1812:                     $brcrum = [{'href' => &Apache::loncommon::authorspace($request->uri),
1.541     raeburn  1813:                                 'text' => 'Authoring Space'},
1.506     droeschl 1814:                                {'href' => '',
                   1815:                                 'text' => $breadcrumbtext}];
1.493     raeburn  1816:                 } else {
1.506     droeschl 1817:                     $brcrum = ''; # FIXME: Where are we?
1.493     raeburn  1818:                 }
1.506     droeschl 1819:                 my %options = ('bread_crumbs' => $brcrum,
                   1820:                                'bgcolor'      => '#FFFFFF');
                   1821:                 $result =
                   1822:                     &Apache::loncommon::start_page(undef,undef,\%options)
                   1823:                    .$controls
                   1824:                    .$result
                   1825:                    .&Apache::loncommon::end_page();
1.493     raeburn  1826:             }
1.495     bisitz   1827:         }
1.147     albertel 1828:     }
1.456     albertel 1829: 
1.78      www      1830: #
                   1831: # Edit action? Insert editing commands
                   1832: #
1.372     albertel 1833:     unless ($env{'request.state'} eq 'published') {
1.427     banghart 1834: 	if ($env{'form.editmode'} && (!($env{'form.viewmode'})) && (!($env{'form.discardview'})))
1.450     albertel 1835: 	{
1.543   ! raeburn  1836:             my ($displayfile,$url,$symb,$itemtitle,$action);
1.530     raeburn  1837: 	    $displayfile=$request->uri;
                   1838:             if ($request->uri =~ m{^/uploaded/}) {
1.534     raeburn  1839:                 if ($env{'request.course.id'}) {
1.539     raeburn  1840:                     if ($request->uri =~ m{^\Q/uploaded/$cdom/$cnum/supplemental/\E}) {
1.534     raeburn  1841:                         &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
                   1842:                                                                 ['folderpath','title']);
1.539     raeburn  1843:                     } elsif ($request->uri =~ m{^\Q/uploaded/$cdom/$cnum/portfolio/syllabus/\E(.+)$}) {
1.540     raeburn  1844:                         my $filename = $1;
                   1845:                         if ($1 eq 'loncapa.html') {
                   1846:                             $displayfile = &mt('Syllabus (minimal template)');
1.543   ! raeburn  1847:                             $action = $request->uri.'?forceedit=1';
1.540     raeburn  1848:                         } else {
                   1849:                             $displayfile = &mt('Syllabus file: [_1]',$1);
                   1850:                         }
1.539     raeburn  1851:                         $itemtitle = &mt('Syllabus');
1.534     raeburn  1852:                     }
                   1853:                 }
1.539     raeburn  1854:                 unless ($itemtitle) {
                   1855:                     ($symb,$itemtitle,$displayfile) = 
                   1856:                         &get_courseupload_hierarchy($request->uri,
                   1857:                                                     $env{'form.folderpath'},
                   1858:                                                     $env{'form.title'});
                   1859:                 }
1.529     raeburn  1860:             } else {
                   1861: 	        $displayfile=~s/^\/[^\/]*//;
                   1862:             }
1.470     albertel 1863: 
1.452     albertel 1864: 	    my ($edit_info, $add_to_onload, $add_to_onresize)=
1.534     raeburn  1865: 		&inserteditinfo($filecontents,$filetype,$displayfile,$symb,
1.543   ! raeburn  1866:                                 $itemtitle,$env{'form.folderpath'},$request->uri,$action);
1.450     albertel 1867: 
                   1868: 	    my %options = 
                   1869: 		('add_entries' =>
1.495     bisitz   1870:                    {'onresize'     => $add_to_onresize,
                   1871:                     'onload'       => $add_to_onload,   });
1.500     raeburn  1872:             my $header;
                   1873:             if ($env{'request.state'} eq 'construct') {
                   1874:                 $options{'bread_crumbs'} = [{
1.523     raeburn  1875:                             'href' => &Apache::loncommon::authorspace($request->uri),
1.541     raeburn  1876:                             'text' => 'Authoring Space'},
1.500     raeburn  1877:                            {'href' => '',
1.502     raeburn  1878:                             'text' => $breadcrumbtext}];
1.500     raeburn  1879:                 $header = &Apache::loncommon::head_subbox(
                   1880:                               &Apache::loncommon::CSTR_pageheader());
                   1881:             }
1.452     albertel 1882: 	    my $js =
                   1883: 		&Apache::edit::js_change_detection().
                   1884: 		&Apache::loncommon::resize_textarea_js();
1.451     albertel 1885: 	    my $start_page = &Apache::loncommon::start_page(undef,$js,
1.402     albertel 1886: 							    \%options);
1.495     bisitz   1887:             $result = $start_page
1.500     raeburn  1888:                      .$header
1.495     bisitz   1889:                      .&Apache::lonxml::message_location()
                   1890:                      .$edit_info
                   1891:                      .&Apache::loncommon::end_page();
1.493     raeburn  1892:         }
1.147     albertel 1893:     }
1.402     albertel 1894:     if ($filetype eq 'html') { &writeallows($request->uri); }
1.501     raeburn  1895: 
1.309     albertel 1896:     &Apache::lonxml::add_messages(\$result);
1.255     sakharuk 1897:     $request->print($result);
                   1898:     
                   1899:     return OK;
1.253     albertel 1900: }
                   1901: 
                   1902: sub display_title {
                   1903:     my $result;
1.372     albertel 1904:     if ($env{'request.state'} eq 'construct') {
1.253     albertel 1905: 	my $title=&Apache::lonnet::gettitle();
                   1906: 	if (!defined($title) || $title eq '') {
1.372     albertel 1907: 	    $title = $env{'request.filename'};
1.253     albertel 1908: 	    $title = substr($title, rindex($title, '/') + 1);
                   1909: 	}
1.476     bisitz   1910:         $result = "<script type='text/javascript'>top.document.title = '$title - LON-CAPA "
1.541     raeburn  1911:                   .&mt('Authoring Space')."';</script>";
1.253     albertel 1912:     }
                   1913:     return $result;
1.24      sakharuk 1914: }
1.147     albertel 1915: 
1.530     raeburn  1916: sub get_courseupload_hierarchy {
1.534     raeburn  1917:     my ($url,$folderpath,$title) = @_;
1.530     raeburn  1918:     my ($symb,$itemtitle,$displaypath);
                   1919:     if ($env{'request.course.id'}) {
1.534     raeburn  1920:         if ($folderpath =~ /^supplemental/) {
                   1921:             my @folders = split(/\&/,$folderpath);
                   1922:             my @pathitems;
                   1923:             while (@folders) {
                   1924:                 my $folder=shift(@folders);
                   1925:                 my $foldername=shift(@folders);
1.538     raeburn  1926:                 $foldername =~ s/\:(\d*)\:(\w*)\:(\w*):(\d*)\:?(\d*)$//;
1.534     raeburn  1927:                 push(@pathitems,&unescape($foldername));
                   1928:             }
                   1929:             if ($title) {
                   1930:                 push(@pathitems,&unescape($title));
                   1931:             }
                   1932:             $displaypath = join(' &raquo; ',@pathitems);
                   1933:         } else {
                   1934:             $symb = &Apache::lonnet::symbread($url);
                   1935:             my ($map,$id,$res)=&Apache::lonnet::decode_symb($symb);
                   1936:             my $navmap=Apache::lonnavmaps::navmap->new;
                   1937:             if (ref($navmap)) {
                   1938:                 my $res = $navmap->getBySymb($symb);
                   1939:                 if (ref($res)) {
                   1940:                     my @pathitems =
                   1941:                         &Apache::loncommon::get_folder_hierarchy($navmap,$map,1);
                   1942:                     $itemtitle = $res->compTitle();
                   1943:                     push(@pathitems,$itemtitle);
                   1944:                     $displaypath = join(' &raquo; ',@pathitems);
                   1945:                 }
1.530     raeburn  1946:             }
                   1947:         }
                   1948:     }
                   1949:     return ($symb,$itemtitle,$displaypath);
                   1950: }
                   1951: 
1.22      albertel 1952: sub debug {
1.298     albertel 1953:     if ($Apache::lonxml::debug eq "1") {
                   1954: 	$|=1;
1.300     albertel 1955: 	my $request=$Apache::lonxml::request;
1.388     albertel 1956: 	if (!$request) {
                   1957: 	    eval { $request=Apache->request; };
                   1958: 	}
                   1959: 	if (!$request) {
                   1960: 	    eval { $request=Apache2::RequestUtil->request; };
                   1961: 	}
1.314     albertel 1962: 	$request->print('<font size="-2"><pre>DEBUG:'.&HTML::Entities::encode($_[0],'<>&"')."</pre></font>\n");
1.346     albertel 1963: 	#&Apache::lonnet::logthis($_[0]);
1.298     albertel 1964:     }
1.22      albertel 1965: }
1.49      albertel 1966: 
1.348     albertel 1967: sub show_error_warn_msg {
1.522     raeburn  1968:     if (($env{'request.filename'} eq 
                   1969:          $Apache::lonnet::perlvar{'lonDocRoot'}.'/res/lib/templates/simpleproblem.problem') &&
                   1970:         (&Apache::lonnet::allowed('mdc',$env{'request.course.id'}))) {
1.351     albertel 1971: 	return 1;
                   1972:     }
1.348     albertel 1973:     return (($Apache::lonxml::debug eq 1) ||
1.372     albertel 1974: 	    ($env{'request.state'} eq 'construct') ||
1.348     albertel 1975: 	    ($Apache::lonhomework::browse eq 'F'
                   1976: 	     &&
1.372     albertel 1977: 	     $env{'form.show_errors'} eq 'on'));
1.348     albertel 1978: }
                   1979: 
1.22      albertel 1980: sub error {
1.454     albertel 1981:     my @errors = @_;
                   1982: 
1.336     albertel 1983:     $errorcount++;
1.454     albertel 1984: 
1.490     www      1985:     $Apache::lonxml::internal_error=1;
                   1986: 
1.454     albertel 1987:     if (defined($Apache::inputtags::part)) {
                   1988: 	if ( @Apache::inputtags::response ) {
                   1989: 	    push(@errors,
                   1990: 		 &mt("This error occurred while processing response [_1] in part [_2]",
                   1991: 		     $Apache::inputtags::response[-1],
                   1992: 		     $Apache::inputtags::part));
                   1993: 	} else {
                   1994: 	    push(@errors,
                   1995: 		 &mt("This error occurred while processing part [_1]",
                   1996: 		     $Apache::inputtags::part));
                   1997: 	}
                   1998:     }
                   1999: 
1.348     albertel 2000:     if ( &show_error_warn_msg() ) {
1.336     albertel 2001: 	# If printing in construction space, put the error inside <pre></pre>
                   2002: 	push(@Apache::lonxml::error_messages,
1.484     bisitz   2003: 	     $Apache::lonxml::warnings_error_header
                   2004:              .'<div class="LC_error">'
                   2005:              .'<b>'.&mt('ERROR:').' </b>'.join("<br />\n",@errors)
                   2006:              ."</div>\n");
1.336     albertel 2007: 	$Apache::lonxml::warnings_error_header='';
                   2008:     } else {
                   2009: 	my $errormsg;
                   2010: 	my ($symb)=&Apache::lonnet::symbread();
                   2011: 	if ( !$symb ) {
                   2012: 	    #public or browsers
1.486     bisitz   2013: 	    $errormsg=&mt("An error occurred while processing this resource. The author has been notified.");
1.403     albertel 2014: 	}
1.413     albertel 2015: 	my $host=$Apache::lonnet::perlvar{'lonHostID'};
1.476     bisitz   2016: 	push(@errors,
                   2017:         &mt("The error occurred on host [_1]",
                   2018:              "<tt>$host</tt>"));
1.454     albertel 2019: 
                   2020: 	my $msg = join('<br />', @errors);
                   2021: 
1.336     albertel 2022: 	#notify author
1.403     albertel 2023: 	&Apache::lonmsg::author_res_msg($env{'request.filename'},$msg);
1.336     albertel 2024: 	#notify course
1.372     albertel 2025: 	if ( $symb && $env{'request.course.id'} ) {
1.380     www      2026: 	    my $cnum=$env{'course.'.$env{'request.course.id'}.'.num'};
                   2027: 	    my $cdom=$env{'course.'.$env{'request.course.id'}.'.domain'};
1.440     albertel 2028: 	    my (undef,%users)=&Apache::lonmsg::decide_receiver(undef,0,1,1,1);
1.372     albertel 2029: 	    my $declutter=&Apache::lonnet::declutter($env{'request.filename'});
1.435     raeburn  2030:             my $baseurl = &Apache::lonnet::clutter($declutter);
1.336     albertel 2031: 	    my @userlist;
                   2032: 	    foreach (keys %users) {
                   2033: 		my ($user,$domain) = split(/:/, $_);
1.531     bisitz   2034: 		push(@userlist,"$user:$domain");
1.380     www      2035: 		my $key=$declutter.'_'.$user.'_'.$domain;
                   2036: 		my %lastnotified=&Apache::lonnet::get('nohist_xmlerrornotifications',
                   2037: 						      [$key],
                   2038: 						      $cdom,$cnum);
                   2039: 		my $now=time;
                   2040: 		if ($now-$lastnotified{$key}>86400) {
1.434     raeburn  2041:                     my $title = &Apache::lonnet::gettitle($symb);
                   2042:                     my $sentmessage;
1.380     www      2043: 		    &Apache::lonmsg::user_normal_msg($user,$domain,
1.435     raeburn  2044: 		        "Error [$title]",$msg,'',$baseurl,'','',
1.434     raeburn  2045:                         \$sentmessage,$symb,$title,1);
1.380     www      2046: 		    &Apache::lonnet::put('nohist_xmlerrornotifications',
                   2047: 					 {$key => $now},
                   2048: 					 $cdom,$cnum);		
                   2049: 		}
1.336     albertel 2050: 	    }
1.372     albertel 2051: 	    if ($env{'request.role.adv'}) {
1.486     bisitz   2052: 		$errormsg=&mt("An error occurred while processing this resource. The course personnel ([_1]) and the author have been notified.",join(', ',@userlist));
1.336     albertel 2053: 	    } else {
1.486     bisitz   2054: 		$errormsg=&mt("An error occurred while processing this resource. The instructor has been notified.");
1.336     albertel 2055: 	    }
                   2056: 	}
1.531     bisitz   2057: 	push(@Apache::lonxml::error_messages,"<span class=\"LC_warning\">$errormsg</span><br />");
1.52      albertel 2058:     }
1.22      albertel 2059: }
1.49      albertel 2060: 
1.22      albertel 2061: sub warning {
1.295     albertel 2062:     $warningcount++;
1.261     albertel 2063:   
1.372     albertel 2064:     if ($env{'form.grade_target'} ne 'tex') {
1.348     albertel 2065: 	if ( &show_error_warn_msg() ) {
1.309     albertel 2066: 	    push(@Apache::lonxml::warning_messages,
1.484     bisitz   2067: 		 $Apache::lonxml::warnings_error_header
                   2068:                 .'<div class="LC_warning">'
                   2069:                 .&mt('[_1]W[_2]ARNING','<b>','</b>')."<b>:</b> ".join('<br />',@_)
                   2070:                 ."</div>\n"
1.482     bisitz   2071:                 );
1.295     albertel 2072: 	    $Apache::lonxml::warnings_error_header='';
                   2073: 	}
                   2074:     }
1.309     albertel 2075: }
                   2076: 
                   2077: sub info {
1.372     albertel 2078:     if ($env{'form.grade_target'} ne 'tex' 
                   2079: 	&& $env{'request.state'} eq 'construct') {
1.309     albertel 2080: 	push(@Apache::lonxml::info_messages,join('<br />',@_)."<br />\n");
                   2081:     }
                   2082: }
                   2083: 
                   2084: sub message_location {
                   2085:     return '__LONCAPA_INTERNAL_MESSAGE_LOCATION__';
                   2086: }
                   2087: 
                   2088: sub add_messages {
                   2089:     my ($msg)=@_;
                   2090:     my $result=join(' ',
                   2091: 		    @Apache::lonxml::info_messages,
                   2092: 		    @Apache::lonxml::error_messages,
                   2093: 		    @Apache::lonxml::warning_messages);
                   2094:     undef(@Apache::lonxml::info_messages);
                   2095:     undef(@Apache::lonxml::error_messages);
                   2096:     undef(@Apache::lonxml::warning_messages);
                   2097:     $$msg=~s/__LONCAPA_INTERNAL_MESSAGE_LOCATION__/$result/;
                   2098:     $$msg=~s/__LONCAPA_INTERNAL_MESSAGE_LOCATION__//g;
1.83      albertel 2099: }
                   2100: 
                   2101: sub get_param {
1.535     foxr     2102:     my ($param,$parstack,$safeeval,$context,$case_insensitive, $noelide) = @_;
                   2103: 
1.213     albertel 2104:     if ( ! $context ) { $context = -1; }
                   2105:     my $args ='';
                   2106:     if ( $#$parstack > (-2-$context) ) { $args=$$parstack[$context]; }
1.297     sakharuk 2107:     if ( ! $Apache::lonxml::usestyle ) {
                   2108: 	$args=$Apache::lonxml::style_values.$args;
                   2109:     }
1.535     foxr     2110: 
                   2111: 
                   2112:     if ($noelide) {
                   2113: #	$args =~ s/\\'/'/g;
                   2114: 	$args =~ s/'\$/'\\\$/g;
                   2115:     }
                   2116: 
1.213     albertel 2117:     if ( ! $args ) { return undef; }
                   2118:     if ( $case_insensitive ) {
1.417     albertel 2119: 	if ($args =~ s/(my (?:.*))(\$\Q$param\E[,\)])/$1.lc($2)/ei) {
1.535     foxr     2120: 
1.213     albertel 2121: 	    return &Apache::run::run("{$args;".'return $'.$param.'}',
                   2122:                                      $safeeval); #'
                   2123: 	} else {
                   2124: 	    return undef;
                   2125: 	}
                   2126:     } else {
1.417     albertel 2127: 	if ( $args =~ /my .*\$\Q$param\E[,\)]/ ) {
1.535     foxr     2128: 	    
1.213     albertel 2129: 	    return &Apache::run::run("{$args;".'return $'.$param.'}',
                   2130:                                      $safeeval); #'
                   2131: 	} else {
                   2132: 	    return undef;
                   2133: 	}
                   2134:     }
1.22      albertel 2135: }
                   2136: 
1.132     albertel 2137: sub get_param_var {
1.213     albertel 2138:   my ($param,$parstack,$safeeval,$context,$case_insensitive) = @_;
1.132     albertel 2139:   if ( ! $context ) { $context = -1; }
                   2140:   my $args ='';
                   2141:   if ( $#$parstack > (-2-$context) ) { $args=$$parstack[$context]; }
1.297     sakharuk 2142:   if ( ! $Apache::lonxml::usestyle ) {
                   2143:       $args=$Apache::lonxml::style_values.$args;
                   2144:   }
1.230     albertel 2145:   &Apache::lonxml::debug("Args are $args param is $param");
1.213     albertel 2146:   if ($case_insensitive) {
1.419     albertel 2147:       if (! ($args=~s/(my (?:.*))(\$\Q$param\E[,\)])/$1.lc($2)/ei)) {
1.213     albertel 2148: 	  return undef;
                   2149:       }
1.419     albertel 2150:   } elsif ( $args !~ /my .*\$\Q$param\E[,\)]/ ) { return undef; }
1.132     albertel 2151:   my $value=&Apache::run::run("{$args;".'return $'.$param.'}',$safeeval); #'
1.230     albertel 2152:   &Apache::lonxml::debug("first run is $value");
1.341     albertel 2153:   if ($value =~ /^[\$\@\%][a-zA-Z_]\w*$/) {
1.230     albertel 2154:       &Apache::lonxml::debug("doing second");
                   2155:       my @result=&Apache::run::run("return $value",$safeeval,1);
                   2156:       if (!defined($result[0])) {
                   2157: 	  return $value
                   2158:       } else {
                   2159: 	  if (wantarray) { return @result; } else { return $result[0]; }
                   2160:       }
1.132     albertel 2161:   } else {
                   2162:     return $value;
                   2163:   }
                   2164: }
                   2165: 
1.438     albertel 2166: sub register_insert_xml {
                   2167:     my $parser = HTML::LCParser->new($Apache::lonnet::perlvar{'lonTabDir'}
                   2168: 				     .'/insertlist.xml');
                   2169:     my ($tagnum,$in_help)=(0,0);
1.442     albertel 2170:     my @alltags;
1.438     albertel 2171:     my $tag;
                   2172:     while (my $token = $parser->get_token()) {
                   2173: 	if ($token->[0] eq 'S') {
                   2174: 	    my $key;
1.525     raeburn  2175: 	    if ($token->[1] eq 'tag') {
1.438     albertel 2176: 		$tag = $token->[2]{'name'};
1.525     raeburn  2177:                 if (defined($tag)) {
                   2178: 		    $insertlist{$tagnum.'.tag'} = $tag;
                   2179: 		    $insertlist{$tag.'.num'}   = $tagnum;
                   2180: 		    push(@alltags,$tag);
                   2181:                 }
1.438     albertel 2182: 	    } elsif ($in_help && $token->[1] eq 'file') {
                   2183: 		$key = $tag.'.helpfile';
                   2184: 	    } elsif ($in_help && $token->[1] eq 'description') {
                   2185: 		$key = $tag.'.helpdesc';
                   2186: 	    } elsif ($token->[1] eq 'description' ||
                   2187: 		     $token->[1] eq 'color'       ||
                   2188: 		     $token->[1] eq 'show'          ) {
                   2189: 		$key = $tag.'.'.$token->[1];
                   2190: 	    } elsif ($token->[1] eq 'insert_sub') {
                   2191: 		$key = $tag.'.function';
                   2192: 	    } elsif ($token->[1] eq 'help') {
                   2193: 		$in_help=1;
                   2194: 	    } elsif ($token->[1] eq 'allow') {
1.442     albertel 2195: 		$key = $tag.'.allow';
1.438     albertel 2196: 	    }
                   2197: 	    if (defined($key)) {
                   2198: 		$insertlist{$key} = $parser->get_text();
                   2199: 		$insertlist{$key} =~ s/(^\s*|\s*$ )//gx;
                   2200: 	    }
                   2201: 	} elsif ($token->[0] eq 'E') {
                   2202: 	    if      ($token->[1] eq 'tag') {
                   2203: 		undef($tag);
                   2204: 		$tagnum++;
                   2205: 	    } elsif ($token->[1] eq 'help') {
                   2206: 		undef($in_help);
                   2207: 	    }
                   2208: 	}
                   2209:     }
1.442     albertel 2210:     
                   2211:     # parse the allows and ignore tags set to <show>no</show>
                   2212:     foreach my $tag (@alltags) {	
1.519     raeburn  2213:         next if (!exists($insertlist{$tag.'.allow'}));
                   2214: 	my $allow =  $insertlist{$tag.'.allow'};
1.442     albertel 2215:        	foreach my $element (split(',',$allow)) {
                   2216: 	    $element =~ s/(^\s*|\s*$ )//gx;
1.519     raeburn  2217: 	    if (!exists($insertlist{$element.'.show'})
                   2218:                 || $insertlist{$element.'.show'} ne 'no') {
1.442     albertel 2219: 		push(@{ $insertlist{$tag.'.which'} },$element);
                   2220: 	    }
                   2221: 	}
                   2222:     }
1.438     albertel 2223: }
                   2224: 
                   2225: sub register_insert {
                   2226:     return &register_insert_xml(@_);
                   2227: #    &dump_insertlist('2');
                   2228: }
                   2229: 
                   2230: sub dump_insertlist {
                   2231:     my ($ext) = @_;
                   2232:     open(XML,">/tmp/insertlist.xml.$ext");
                   2233:     print XML ("<insertlist>");
                   2234:     my $i=0;
                   2235: 
                   2236:     while (exists($insertlist{"$i.tag"})) {
                   2237: 	my $tag = $insertlist{"$i.tag"};
                   2238: 	print XML ("
                   2239: \t<tag name=\"$tag\">");
                   2240: 	if (defined($insertlist{"$tag.description"})) {
                   2241: 	    print XML ("
                   2242: \t\t<description>".$insertlist{"$tag.description"}."</description>");
                   2243: 	}
                   2244: 	if (defined($insertlist{"$tag.color"})) {
                   2245: 	    print XML ("
                   2246: \t\t<color>".$insertlist{"$tag.color"}."</color>");
                   2247: 	}
                   2248: 	if (defined($insertlist{"$tag.function"})) {
                   2249: 	    print XML ("
                   2250: \t\t<insert_sub>".$insertlist{"$tag.function"}."</insert_sub>");
                   2251: 	}
                   2252: 	if (defined($insertlist{"$tag.show"})
                   2253: 	    && $insertlist{"$tag.show"} ne 'yes') {
                   2254: 	    print XML ("
                   2255: \t\t<show>".$insertlist{"$tag.show"}."</show>");
                   2256: 	}
                   2257: 	if (defined($insertlist{"$tag.helpfile"})) {
                   2258: 	    print XML ("
                   2259: \t\t<help>
                   2260: \t\t\t<file>".$insertlist{"$tag.helpfile"}."</file>");
                   2261: 	    if ($insertlist{"$tag.helpdesc"} ne '') {
                   2262: 		print XML ("
                   2263: \t\t\t<description>".$insertlist{"$tag.helpdesc"}."</description>");
                   2264: 	    }
                   2265: 	    print XML ("
                   2266: \t\t</help>");
                   2267: 	}
                   2268: 	if (defined($insertlist{"$tag.which"})) {
                   2269: 	    print XML ("
                   2270: \t\t<allow>".join(',',sort(@{ $insertlist{"$tag.which"} }))."</allow>");
                   2271: 	}
                   2272: 	print XML ("
                   2273: \t</tag>");
                   2274: 	$i++;
                   2275:     }
                   2276:     print XML ("\n</insertlist>\n");
                   2277:     close(XML);
                   2278: }
                   2279: 
1.98      albertel 2280: sub description {
1.437     albertel 2281:     my ($token)=@_;
                   2282:     my $tag = &get_tag($token);
                   2283:     return $insertlist{$tag.'.description'};
1.268     bowersj2 2284: }
                   2285: 
                   2286: # Returns a list containing the help file, and the description
                   2287: sub helpinfo {
1.437     albertel 2288:     my ($token)=@_;
                   2289:     my $tag = &get_tag($token);
                   2290:     return ($insertlist{$tag.'.helpfile'}, $insertlist{$tag.'.helpdesc'});
                   2291: }
                   2292: 
                   2293: sub get_tag {
                   2294:     my ($token)=@_;
                   2295:     my $tagnum;
                   2296:     my $tag=$token->[1];
                   2297:     foreach my $namespace (reverse(@Apache::lonxml::namespace)) {
                   2298: 	my $testtag = $namespace.'::'.$tag;
                   2299: 	$tagnum = $insertlist{"$testtag.num"};
                   2300: 	last if (defined($tagnum));
                   2301:     }
                   2302:     if (!defined($tagnum)) {
                   2303: 	$tagnum = $Apache::lonxml::insertlist{"$tag.num"};
                   2304:     }
                   2305:     return $insertlist{"$tagnum.tag"};
1.98      albertel 2306: }
1.123     albertel 2307: 
1.485     onken    2308: ############################################################
                   2309: #                                           PDF-FORM-METHODS
                   2310: 
                   2311: =pod
                   2312: 
1.508     onken    2313: =item &print_pdf_radiobutton(fieldname, value)
1.485     onken    2314: 
1.508     onken    2315: Returns a latexline to generate a PDF-Form-Radiobutton.
                   2316: Note: Radiobuttons with equal names are automaticly grouped 
                   2317:       in a selection-group.
1.485     onken    2318: 
1.508     onken    2319: $fieldname: PDF internalname of the radiobutton(group)
                   2320: $value:     Value of radiobutton
1.485     onken    2321: 
                   2322: =cut
                   2323: sub print_pdf_radiobutton {
1.508     onken    2324:     my ($fieldname, $value) = @_;
                   2325:     return '\radioButton[\symbolchoice{circle}]{'
                   2326:            .$fieldname.'}{10bp}{10bp}{'.$value.'}';
1.485     onken    2327: }
                   2328: 
                   2329: 
                   2330: =pod
                   2331: 
                   2332: =item &print_pdf_start_combobox(fieldname)
                   2333: 
                   2334: Starts a latexline to generate a PDF-Form-Combobox with text.
                   2335: 
                   2336: $fieldname: PDF internal name of the Combobox
                   2337: 
                   2338: =cut
                   2339: sub print_pdf_start_combobox {
                   2340:     my $result;
                   2341:     my ($fieldName) = @_;
                   2342:     $result .= '\begin{tabularx}{\textwidth}{p{2.5cm}X}'."\n";
                   2343:     $result .= '\comboBox[]{'.$fieldName.'}{2.3cm}{14bp}{'; # 
                   2344: 
                   2345:     return $result;
                   2346: }
                   2347: 
                   2348: 
                   2349: =pod
                   2350: 
                   2351: =item &print_pdf_add_combobox_option(options)
                   2352: 
                   2353: Generates a latexline to add Options to a PDF-Form-ComboBox.
                   2354: 
                   2355: $option: PDF internal name of the Combobox-Option
                   2356: 
                   2357: =cut
                   2358: sub print_pdf_add_combobox_option {
                   2359: 
                   2360:     my $result;
                   2361:     my ($option) = @_;  
                   2362: 
                   2363:     $result .= '('.$option.')';
                   2364:     
                   2365:     return $result;
                   2366: }
                   2367: 
                   2368: 
                   2369: =pod
                   2370: 
                   2371: =item &print_pdf_end_combobox(text) {
                   2372: 
                   2373: Returns latexcode to end a PDF-Form-Combobox with text.
                   2374: 
                   2375: =cut
                   2376: sub print_pdf_end_combobox {
                   2377:     my $result;
                   2378:     my ($text) = @_;
                   2379: 
                   2380:     $result .= '}&'.$text."\\\\\n";
                   2381:     $result .= '\end{tabularx}' . "\n";
                   2382:     $result .= '\hspace{2mm}' . "\n";
                   2383:     return $result;
                   2384: }
                   2385: 
                   2386: 
                   2387: =pod
                   2388: 
                   2389: =item &print_pdf_hiddenField(fieldname, user, domain)
                   2390: 
                   2391: Returns a latexline to generate a PDF-Form-hiddenField with userdata.
                   2392: 
                   2393: $fieldname label for hiddentextfield
                   2394: $user:    name of user
                   2395: $domain:  domain of user
                   2396: 
                   2397: =cut
                   2398: sub print_pdf_hiddenfield {
                   2399:     my $result;
                   2400:     my ($fieldname, $user, $domain) = @_;
                   2401: 
                   2402:     $result .= '\textField [\F{\FHidden}\F{-\FPrint}\V{'.$domain.'&'.$user.'}]{'.$fieldname.'}{0in}{0in}'."\n";
                   2403: 
                   2404:     return $result;
                   2405: }
                   2406: 
1.1       sakharuk 2407: 1;
                   2408: __END__
1.68      www      2409: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>
500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.