--- loncom/xml/lonxml.pm 2000/06/27 20:33:54 1.5 +++ loncom/xml/lonxml.pm 2001/06/02 03:59:59 1.84 @@ -2,193 +2,783 @@ # XML Parser Module # # last modified 06/26/00 by Alexander Sakharuk +# 11/6 Gerd Kortemeyer +# 6/1/1 Gerd Kortemeyer +# 2/21,3/13 Guy +# 3/29,5/4 Gerd Kortemeyer +# 5/10 Scott Harrison +# 5/26 Gerd Kortemeyer +# 5/27 H. K. Ng package Apache::lonxml; - +use vars +qw(@pwd @outputstack $redirection $import @extlinks $metamode $evaluate %insertlist @namespace); use strict; use HTML::TokeParser; use Safe; -use Apache::style; +use Safe::Hole; +use Math::Cephes qw(:trigs :hypers :bessels erf erfc); +use Opcode; + +sub register { + my $space; + my @taglist; + my $temptag; + ($space,@taglist) = @_; + foreach $temptag (@taglist) { + $Apache::lonxml::alltags{$temptag}=$space; + } +} + +use Apache::Constants qw(:common); use Apache::lontexconvert; +use Apache::style; +use Apache::run; use Apache::londefdef; +use Apache::scripttag; +use Apache::edit; +use Apache::lonnet; +use Apache::File; + #================================================== Main subroutine: xmlparse +#debugging control, to turn on debugging modify the correct handler +$Apache::lonxml::debug=0; + +#path to the directory containing the file currently being processed +@pwd=(); + +#these two are used for capturing a subset of the output for later processing, +#don't touch them directly use &startredirection and &endredirection +@outputstack = (); +$redirection = 0; + +#controls wheter the tag actually does +$import = 1; +@extlinks=(); + +# meta mode is a bit weird only some output is to be turned off +# tag turns metamode off (defined in londefdef.pm) +$metamode = 0; + +# turns on and of run::evaluate actually derefencing var refs +$evaluate = 1; + +# data structure for eidt mode, determines what tags can go into what other tags +%insertlist=(); + +#stores the list of active tag namespaces +@namespace=(); + +sub xmlbegin { + my $output=''; + if ($ENV{'browser.mathml'}) { + $output='' + .'' + .']>' + .''; + } else { + $output=''; + } + return $output; +} + +sub xmlend { + return ''; +} + +sub fontsettings() { + my $headerstring=''; + if (($ENV{'browser.os'} eq 'mac') && (!$ENV{'browser.mathml'})) { + $headerstring.= + ''; + } + return $headerstring; +} + +sub registerurl { + return (< +// BEGIN LON-CAPA Internal + function LONCAPAreg() { + if (window.location.pathname!="/res/adm/pages/menu.html") { + menu=window.open("","LONCAPAmenu"); + menu.currentURL=window.location.pathname; + menu.currentStale=0; + } + } + + function LONCAPAstale() { + if (window.location.pathname!="/res/adm/pages/menu.html") { + menu=window.open("","LONCAPAmenu"); + menu.currentStale=1; + } + } +// END LON-CAPA Internal + +ENDSCRIPT +} + +sub loadevents() { + return 'LONCAPAreg();'; +} + +sub unloadevents() { + return 'LONCAPAstale();'; +} + +sub printalltags { + my $temp; + foreach $temp (sort keys %Apache::lonxml::alltags) { + &Apache::lonxml::debug("$temp -- $Apache::lonxml::alltags{$temp}"); + } +} sub xmlparse { - my ($target,$content_file_string,%style_for_target) = @_; - my $pars = HTML::TokeParser->new(\$content_file_string); + my ($target,$content_file_string,$safeinit,%style_for_target) = @_; + if ($target eq 'meta') { + $Apache::lonxml::redirection = 0; + $Apache::lonxml::metamode = 1; + $Apache::lonxml::evaluate = 1; + $Apache::lonxml::import = 0; + } elsif ($target eq 'grade') { + &startredirection; + $Apache::lonxml::metamode = 0; + $Apache::lonxml::evaluate = 1; + $Apache::lonxml::import = 1; + } elsif ($target eq 'modified') { + $Apache::lonxml::redirection = 0; + $Apache::lonxml::metamode = 0; + $Apache::lonxml::evaluate = 0; + $Apache::lonxml::import = 0; + } else { + $Apache::lonxml::redirection = 0; + $Apache::lonxml::metamode = 0; + $Apache::lonxml::evaluate = 1; + $Apache::lonxml::import = 1; + } + #&printalltags(); + my @pars = (); + @Apache::lonxml::pwd=(); + my $pwd=$ENV{'request.filename'}; + $pwd =~ s:/[^/]*$::; + &newparser(\@pars,\$content_file_string,$pwd); my $currentstring = ''; my $finaloutput = ''; my $newarg = ''; - my $tempostring = ''; - my $tempocont = ''; - my $safeeval = new Safe; + my $result; + my $safeeval = new Safe; + my $safehole = new Safe::Hole; + &init_safespace($target,$safeeval,$safehole,$safeinit); #-------------------- Redefinition of the target in the case of compound target ($target, my @tenta) = split('&&',$target); -#------------------------- Stack definition (in stack we have all current tags) - my @stack = (); my @parstack = (); - -#------------------------------------- Parse input string (content_file_string) - + &initdepth; my $token; - - while ($token = $pars->get_token) { - if ($token->[0] eq 'T') { - $finaloutput .= $token->[1]; - $tempocont .= $token->[1]; - } elsif ($token->[0] eq 'S') { -#------------------------------------------------------------- add tag to stack - push (@stack,$token->[1]); -#----------------------------------------- add parameters list to another stack - map {$tempostring .= "$_=$token->[2]->{$_},"} @{$token->[3]}; - push (@parstack,$tempostring); - $tempostring = ''; - - if (exists $style_for_target{$token->[1]}) { - -#---------------------------------------------------- use style file definition - - $newarg = $style_for_target{$token->[1]}; - - if (index($newarg,'script') != -1 ) { - my $pat = HTML::TokeParser->new(\$newarg); - my $tokenpat; - my $partstring = ''; - my $oustring = ''; - my $outputstring; - - while ($tokenpat = $pat->get_token) { - if ($tokenpat->[0] eq 'T') { - $oustring .= $tokenpat->[1]; - } elsif ($tokenpat->[0] eq 'S') { - if ($tokenpat->[1] eq 'script') { - while ($tokenpat = $pat->get_token and $tokenpat->[1] ne 'script') { - if ($tokenpat->[0] eq 'S') { - $partstring .= $tokenpat->[4]; - } elsif ($tokenpat->[0] eq 'T') { - $partstring .= $tokenpat->[1]; - } elsif ($tokenpat->[0] eq 'E') { - $partstring .= $tokenpat->[2]; - } - } - - map {$partstring =~ s/\$$_/$token->[2]->{$_}/g; } @{$token->[3]}; - - &run($partstring,$safeeval); - - $partstring = ''; - } elsif ($tokenpat->[1] eq 'evaluate') { - $outputstring = &evaluate($tokenpat->[2]{expression},$safeeval); - $oustring .= $outputstring; - } else { - $oustring .= $tokenpat->[4]; - } - } elsif ($tokenpat->[0] eq 'E' and $tokenpat->[1] ne 'evaluate') { - $oustring .= $tokenpat->[1]; - } + while ( $#pars > -1 ) { + while ($token = $pars[$#pars]->get_token) { + if (($token->[0] eq 'T') || ($token->[0] eq 'C') || ($token->[0] eq 'D') ) { + if ($metamode<1) { $result=$token->[1]; } + } elsif ($token->[0] eq 'PI') { + if ($metamode<1) { $result=$token->[2]; } + } elsif ($token->[0] eq 'S') { + # add tag to stack + push (@stack,$token->[1]); + # add parameters list to another stack + push (@parstack,&parstring($token)); + &increasedepth($token); + if (exists $style_for_target{$token->[1]}) { + if ($Apache::lonxml::redirection) { + $Apache::lonxml::outputstack['-1'] .= + &recurse($style_for_target{$token->[1]},$target,$safeeval, + \%style_for_target,@parstack); + } else { + $finaloutput .= &recurse($style_for_target{$token->[1]},$target, + $safeeval,\%style_for_target,@parstack); } - $newarg = $oustring; } else { - map {$newarg =~ s/\$$_/$token->[2]->{$_}/g; } @{$token->[3]}; + $result = &callsub("start_$token->[1]", $target, $token, \@stack, + \@parstack, \@pars, $safeeval, \%style_for_target); + } + } elsif ($token->[0] eq 'E') { + #clear out any tags that didn't end + while ($token->[1] ne $stack[$#stack] && ($#stack > -1)) { + &Apache::lonxml::warning("Unbalanced tags in resource $stack['-1']"); + pop @stack;pop @parstack;&decreasedepth($token); } - $finaloutput .= $newarg; - } else { - # use default definition of tag - my $sub="start_$token->[1]"; - { - no strict 'refs'; - if (defined (&$sub)) { - $currentstring = &$sub($target,$token,\@parstack); - $finaloutput .= $currentstring; - $currentstring = ''; + + if (exists $style_for_target{'/'."$token->[1]"}) { + if ($Apache::lonxml::redirection) { + $Apache::lonxml::outputstack['-1'] .= + &recurse($style_for_target{'/'."$token->[1]"}, + $target,$safeeval,\%style_for_target,@parstack); } else { - $finaloutput .= $token->[4]; + $finaloutput .= &recurse($style_for_target{'/'."$token->[1]"}, + $target,$safeeval,\%style_for_target, + @parstack); } - use strict 'refs'; + + } else { + $result = &callsub("end_$token->[1]", $target, $token, \@stack, + \@parstack, \@pars,$safeeval, \%style_for_target); } - } - } elsif ($token->[0] eq 'E') { - # Put here check for correct final tag (to avoid existence of - # starting tag only) - - pop @stack; - unless (exists $style_for_target{$token->[1]}) { - my $sub="end_$token->[1]"; - { - no strict 'refs'; - if (defined(&$sub)) { - $currentstring = &$sub($target,$token,\@parstack); - $finaloutput .= $currentstring; - $currentstring = ''; + } else { + &Apache::lonxml::error("Unknown token event :$token->[0]:$token->[1]:"); + } + #evaluate variable refs in result + if ($result ne "") { + if ( $#parstack > -1 ) { + if ($Apache::lonxml::redirection) { + $Apache::lonxml::outputstack['-1'] .= + &Apache::run::evaluate($result,$safeeval,$parstack[$#parstack]); } else { - $finaloutput .= $token->[4]; + $finaloutput .= &Apache::run::evaluate($result,$safeeval, + $parstack[$#parstack]); } - use strict 'refs'; + } else { + $finaloutput .= &Apache::run::evaluate($result,$safeeval,''); } + $result = ''; + } + if ($token->[0] eq 'E') { + pop @stack;pop @parstack;&decreasedepth($token); } - #---- end tag from the style file - if (exists $style_for_target{'/'."$token->[1]"}) { - $newarg = $style_for_target{'/'."$token->[1]"}; - if (index($newarg,'script') != -1 ) { - my $pat = HTML::TokeParser->new(\$newarg); - my $tokenpat; - my $partstring = ''; - my $oustring = ''; - my $outputstring; - - while ($tokenpat = $pat->get_token) { - if ($tokenpat->[0] eq 'T') { - $oustring .= $tokenpat->[1]; - } elsif ($tokenpat->[0] eq 'S') { - if ($tokenpat->[1] eq 'script') { - while ($tokenpat = $pat->get_token and $tokenpat->[1] ne 'script') { - if ($tokenpat->[0] eq 'S') { - $partstring .= $tokenpat->[4]; - } elsif ($tokenpat->[0] eq 'T') { - $partstring .= $tokenpat->[1]; - } elsif ($tokenpat->[0] eq 'E') { - $partstring .= $tokenpat->[2]; - } - } - - my @tempor_list = split(',',$parstack[$#parstack]); - my @te_kl = (); - my %tempor_hash = (); - map {(my $onete,my $twote) = split('=',$_); push (@te_kl,$onete); - $tempor_hash{$onete} = $twote} @tempor_list; - map {$partstring =~ s/\$$_/$tempor_hash{$_}/g; } @te_kl; - - &run($partstring,$safeeval); - - $partstring = ''; - } elsif ($tokenpat->[1] eq 'evaluate') { - $outputstring = &evaluate($tokenpat->[2]{expression},$safeeval); - $oustring .= $outputstring; - } else { - $oustring .= $tokenpat->[4]; - } - } elsif ($tokenpat->[0] eq 'E' and $tokenpat->[1] ne 'evaluate') { - $oustring .= $tokenpat->[1]; - } - } - $newarg = $oustring; + } + pop @pars; + pop @Apache::lonxml::pwd; + } + +# if ($target eq 'meta') { +# $finaloutput.=&endredirection; +# } + + if (($ENV{'QUERY_STRING'}) && ($target eq 'web')) { + $finaloutput=&afterburn($finaloutput); + } + + return $finaloutput; +} + + +sub recurse { + + my @innerstack = (); + my @innerparstack = (); + my ($newarg,$target,$safeeval,$style_for_target,@parstack) = @_; + my @pat = (); + &newparser(\@pat,\$newarg); + my $tokenpat; + my $partstring = ''; + my $output=''; + my $decls=''; + while ( $#pat > -1 ) { + while ($tokenpat = $pat[$#pat]->get_token) { + if (($tokenpat->[0] eq 'T') || ($tokenpat->[0] eq 'C') || ($tokenpat->[0] eq 'D') ) { + if ($metamode<1) { $partstring=$tokenpat->[1]; } + } elsif ($tokenpat->[0] eq 'PI') { + if ($metamode<1) { $partstring=$tokenpat->[2]; } + } elsif ($tokenpat->[0] eq 'S') { + push (@innerstack,$tokenpat->[1]); + push (@innerparstack,&parstring($tokenpat)); + &increasedepth($tokenpat); + $partstring = &callsub("start_$tokenpat->[1]", $target, $tokenpat, + \@innerstack, \@innerparstack, \@pat, + $safeeval, $style_for_target); + } elsif ($tokenpat->[0] eq 'E') { + #clear out any tags that didn't end + while ($tokenpat->[1] ne $innerstack[$#innerstack] + && ($#innerstack > -1)) { + &Apache::lonxml::warning("Unbalanced tags in resource $innerstack['-1']"); + pop @innerstack;pop @innerparstack;&decreasedepth($tokenpat); + } + $partstring = &callsub("end_$tokenpat->[1]", $target, $tokenpat, + \@innerstack, \@innerparstack, \@pat, + $safeeval, $style_for_target); + } else { + &Apache::lonxml::error("Unknown token event :$tokenpat->[0]:$tokenpat->[1]:"); + } + #pass both the variable to the style tag, and the tag we + #are processing inside the + if ( $partstring ne "" ) { + if ( $#parstack > -1 ) { + if ( $#innerparstack > -1 ) { + $decls= $parstack[$#parstack].$innerparstack[$#innerparstack]; + } else { + $decls= $parstack[$#parstack]; + } + } else { + if ( $#innerparstack > -1 ) { + $decls=$innerparstack[$#innerparstack]; + } else { + $decls=''; + } + } + $output .= &Apache::run::evaluate($partstring,$safeeval,$decls); + $partstring = ''; + } + if ($tokenpat->[0] eq 'E') { pop @innerstack;pop @innerparstack; + &decreasedepth($tokenpat);} + } + pop @pat; + pop @Apache::lonxml::pwd; + } + return $output; +} + +sub callsub { + my ($sub,$target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; + my $currentstring=''; + my $nodefault; + { + my $sub1; + no strict 'refs'; + if ($target eq 'edit' && $token->[0] eq 'S') { + $currentstring = &Apache::edit::tag_start($target,$token,$tagstack, + $parstack,$parser, + $safeeval,$style); + } + my $tag=$token->[1]; + my $space=$Apache::lonxml::alltags{$tag}; + if (!$space) { + $tag=~tr/A-Z/a-z/; + $sub=~tr/A-Z/a-z/; + $space=$Apache::lonxml::alltags{$tag} + } + if ($space) { + #&Apache::lonxml::debug("Calling sub $sub in $space $metamode
\n"); + $sub1="$space\:\:$sub"; + $Apache::lonxml::curdepth=join('_',@Apache::lonxml::depthcounter); + ($currentstring,$nodefault) = &$sub1($target,$token,$tagstack, + $parstack,$parser,$safeeval, + $style); + } else { + #&Apache::lonxml::debug("NOT Calling sub $sub in $space $metamode
\n"); + if ($metamode <1) { + if (defined($token->[4]) && ($metamode < 1)) { + $currentstring = $token->[4]; + } else { + $currentstring = $token->[2]; + } + } + } +# &Apache::lonxml::debug("nodefalt:$nodefault:"); + if ($currentstring eq '' && $nodefault eq '') { + if ($target eq 'edit') { + &Apache::lonxml::debug("doing default edit for $token->[1]"); + if ($token->[0] eq 'S') { + $currentstring = &Apache::edit::tag_start($target,$token); + } elsif ($token->[0] eq 'E') { + $currentstring = &Apache::edit::tag_end($target,$token); + } + } elsif ($target eq 'modified') { + if ($token->[0] eq 'S') { + $currentstring = $token->[4]; + $currentstring.=&Apache::edit::handle_insert(); + } else { + $currentstring = $token->[2]; + } + } + } + use strict 'refs'; + } + return $currentstring; +} + +sub init_safespace { + my ($target,$safeeval,$safehole,$safeinit) = @_; + $safeeval->permit("entereval"); + $safeeval->permit(":base_math"); + $safeeval->permit("sort"); + $safeeval->deny(":base_io"); + $safehole->wrap(\&Apache::lonnet::EXT,$safeeval,'&EXT'); + + $safehole->wrap(\&Math::Cephes::asin,$safeeval,'&asin'); + $safehole->wrap(\&Math::Cephes::acos,$safeeval,'&acos'); + $safehole->wrap(\&Math::Cephes::atan,$safeeval,'&atan'); + $safehole->wrap(\&Math::Cephes::sinh,$safeeval,'&sinh'); + $safehole->wrap(\&Math::Cephes::cosh,$safeeval,'&cosh'); + $safehole->wrap(\&Math::Cephes::tanh,$safeeval,'&tanh'); + $safehole->wrap(\&Math::Cephes::asinh,$safeeval,'&asinh'); + $safehole->wrap(\&Math::Cephes::acosh,$safeeval,'&acosh'); + $safehole->wrap(\&Math::Cephes::atanh,$safeeval,'&atanh'); + $safehole->wrap(\&Math::Cephes::erf,$safeeval,'&erf'); + $safehole->wrap(\&Math::Cephes::erfc,$safeeval,'&erfc'); + $safehole->wrap(\&Math::Cephes::j0,$safeeval,'&j0'); + $safehole->wrap(\&Math::Cephes::j1,$safeeval,'&j1'); + $safehole->wrap(\&Math::Cephes::jn,$safeeval,'&jn'); + $safehole->wrap(\&Math::Cephes::jv,$safeeval,'&jv'); + $safehole->wrap(\&Math::Cephes::y0,$safeeval,'&y0'); + $safehole->wrap(\&Math::Cephes::y1,$safeeval,'&y1'); + $safehole->wrap(\&Math::Cephes::yn,$safeeval,'&yn'); + $safehole->wrap(\&Math::Cephes::yv,$safeeval,'&yv'); + +#need to inspect this class of ops +# $safeeval->deny(":base_orig"); + $safeinit .= ';$external::target='.$target.';'; + $safeinit .= ';$external::randomseed='.&Apache::lonnet::rndseed().';'; + &Apache::run::run($safeinit,$safeeval); +} + +sub startredirection { + $Apache::lonxml::redirection++; + push (@Apache::lonxml::outputstack, ''); +} + +sub endredirection { + if (!$Apache::lonxml::redirection) { + &Apache::lonxml::error("Endredirection was called, before a startredirection, perhaps you have unbalanced tags. Some debuging information:".join ":",caller); + return ''; + } + $Apache::lonxml::redirection--; + pop @Apache::lonxml::outputstack; +} + +sub initdepth { + @Apache::lonxml::depthcounter=(); + $Apache::lonxml::depth=-1; + $Apache::lonxml::olddepth=-1; +} + +sub increasedepth { + my ($token) = @_; + $Apache::lonxml::depth++; + $Apache::lonxml::depthcounter[$Apache::lonxml::depth]++; + if ($Apache::lonxml::depthcounter[$Apache::lonxml::depth]==1) { + $Apache::lonxml::olddepth=$Apache::lonxml::depth; + } + my $curdepth=join('_',@Apache::lonxml::depthcounter); + &Apache::lonxml::debug("s $Apache::lonxml::depth : $Apache::lonxml::olddepth : $curdepth : $token->[1]\n"); +#print "
s $Apache::lonxml::depth : $Apache::lonxml::olddepth : $curdepth : $token->[1]\n"; +} + +sub decreasedepth { + my ($token) = @_; + $Apache::lonxml::depth--; + if ($Apache::lonxml::depth<$Apache::lonxml::olddepth-1) { + $#Apache::lonxml::depthcounter--; + $Apache::lonxml::olddepth=$Apache::lonxml::depth+1; + } + if ( $Apache::lonxml::depth < -1) { + &Apache::lonxml::warning("Unbalanced tags in resource"); + $Apache::lonxml::depth='-1'; + } + my $curdepth=join('_',@Apache::lonxml::depthcounter); + &Apache::lonxml::debug("e $Apache::lonxml::depth : $Apache::lonxml::olddepth : $token->[1] : $curdepth\n"); +#print "
e $Apache::lonxml::depth : $Apache::lonxml::olddepth : $token->[1] : $curdepth\n"; +} + +sub get_all_text { + + my($tag,$pars)= @_; + my $depth=0; + my $token; + my $result=''; + if ( $tag =~ m:^/: ) { + my $tag=substr($tag,1); +# &Apache::lonxml::debug("have:$tag:"); + while (($depth >=0) && ($token = $pars->get_token)) { +# &Apache::lonxml::debug("e token:$token->[0]:$depth:$token->[1]"); + if (($token->[0] eq 'T')||($token->[0] eq 'C')||($token->[0] eq 'D')) { + $result.=$token->[1]; + } elsif ($token->[0] eq 'PI') { + $result.=$token->[2]; + } elsif ($token->[0] eq 'S') { + if ($token->[1] eq $tag) { $depth++; } + $result.=$token->[4]; + } elsif ($token->[0] eq 'E') { + if ( $token->[1] eq $tag) { $depth--; } + #skip sending back the last end tag + if ($depth > -1) { $result.=$token->[2]; } else { + $pars->unget_token($token); + } + } + } + } else { + while ($token = $pars->get_token) { +# &Apache::lonxml::debug("s token:$token->[0]:$depth:$token->[1]"); + if (($token->[0] eq 'T')||($token->[0] eq 'C')||($token->[0] eq 'D')) { + $result.=$token->[1]; + } elsif ($token->[0] eq 'PI') { + $result.=$token->[2]; + } elsif ($token->[0] eq 'S') { + if ( $token->[1] eq $tag) { + $pars->unget_token($token); last; } else { - my @very_temp = split(',',$parstack[$#parstack]); - map {my @ret= split('=',$_); $newarg =~ s/\$$ret[0]/$ret[1]/g; } @very_temp; + $result.=$token->[4]; } - - $finaloutput .= $newarg; + } elsif ($token->[0] eq 'E') { + $result.=$token->[2]; } - pop @parstack; } } - return $finaloutput; +# &Apache::lonxml::debug("Exit:$result:"); + return $result +} + +sub newparser { + my ($parser,$contentref,$dir) = @_; + push (@$parser,HTML::TokeParser->new($contentref)); + $$parser['-1']->xml_mode('1'); + if ( $dir eq '' ) { + push (@Apache::lonxml::pwd, $Apache::lonxml::pwd[$#Apache::lonxml::pwd]); + } else { + push (@Apache::lonxml::pwd, $dir); + } +# &Apache::lonxml::debug("pwd:$#Apache::lonxml::pwd"); +# &Apache::lonxml::debug("pwd:$Apache::lonxml::pwd[$#Apache::lonxml::pwd]"); +} + +sub parstring { + my ($token) = @_; + my $temp=''; + map { + unless ($_=~/\W/) { + my $val=$token->[2]->{$_}; + $val =~ s/([\%\@\\])/\\$1/g; + #if ($val =~ m/^[\%\@]/) { $val="\\".$val; } + $temp .= "my \$$_=\"$val\";" + } + } @{$token->[3]}; + return $temp; +} + +sub writeallows { + my $thisurl='/res/'.&Apache::lonnet::declutter(shift); + my $thisdir=$thisurl; + $thisdir=~s/\/[^\/]+$//; + my %httpref=(); + map { + $httpref{'httpref.'. + &Apache::lonnet::hreflocation($thisdir,$_)}=$thisurl; } @extlinks; + &Apache::lonnet::appenv(%httpref); } +# +# Afterburner handles anchors, highlights and links +# +sub afterburn { + my $result=shift; + map { + my ($name, $value) = split(/=/,$_); + $value =~ tr/+/ /; + $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg; + if (($name eq 'highlight')||($name eq 'anchor')||($name eq 'link')) { + unless ($ENV{'form.'.$name}) { + $ENV{'form.'.$name}=$value; + } + } + } (split(/&/,$ENV{'QUERY_STRING'})); + if ($ENV{'form.highlight'}) { + map { + my $anchorname=$_; + my $matchthis=$anchorname; + $matchthis=~s/\_+/\\s\+/g; + $result=~s/($matchthis)/\$1\<\/font\>/gs; + } split(/\,/,$ENV{'form.highlight'}); + } + if ($ENV{'form.link'}) { + map { + my ($anchorname,$linkurl)=split(/\>/,$_); + my $matchthis=$anchorname; + $matchthis=~s/\_+/\\s\+/g; + $result=~s/($matchthis)/\$1\<\/a\>/gs; + } split(/\,/,$ENV{'form.link'}); + } + if ($ENV{'form.anchor'}) { + my $anchorname=$ENV{'form.anchor'}; + my $matchthis=$anchorname; + $matchthis=~s/\_+/\\s\+/g; + $result=~s/($matchthis)/\$1\<\/a\>/s; + $result.=(<<"ENDSCRIPT"); + +ENDSCRIPT + } + return $result; +} + +sub storefile { + my ($file,$contents)=@_; + if (my $fh=Apache::File->new('>'.$file)) { + print $fh $contents; + $fh->close(); + } +} + +sub inserteditinfo { + my ($result,$filecontents)=@_; + unless ($filecontents) { + $filecontents=(< + + + Title of Document Goes Here + + + + + Body of Document Goes Here + + + +SIMPLECONTENT + } + my $editheader='Edit below
'; + my $editfooter=(< + +
+ +
+ +
+ENDFOOTER + $result=~s/(\]*\>)/$1$editheader/is; + $result=~s/(\<\/body\>)/$editfooter/is; + return $result; +} + +sub handler { + my $request=shift; + + my $target='web'; + + $Apache::lonxml::debug=0; + + if ($ENV{'browser.mathml'}) { + $request->content_type('text/xml'); + } else { + $request->content_type('text/html'); + } + + $request->send_http_header; + + return OK if $request->header_only; + + + my $file=&Apache::lonnet::filelocation("",$request->uri); +# +# Edit action? Save file. +# + unless ($ENV{'request.state'} eq 'published') { + if ($ENV{'form.savethisfile'}) { + &storefile($file,$ENV{'form.filecont'}); + } + } + my %mystyle; + my $result = ''; + my $filecontents=&Apache::lonnet::getfile($file); + if ($filecontents == -1) { + $result=(< + +File not found + + +File not found: $file + + +ENDNOTFOUND + $filecontents=''; + } else { + $result = &Apache::lonxml::xmlparse($target,$filecontents,'',%mystyle); + } + +# +# Edit action? Insert editing commands +# + unless ($ENV{'request.state'} eq 'published') { + $result=&inserteditinfo($result,$filecontents); + } + + $request->print($result); + + writeallows($request->uri); + return OK; +} + +sub debug { + if ($Apache::lonxml::debug eq 1) { + print "DEBUG:".$_[0]."
\n"; + } +} + +sub error { + if (($Apache::lonxml::debug eq 1) || ($ENV{'request.state'} eq 'construct') ) { + print "ERROR:".$_[0]."
\n"; + } else { + print "An Error occured while processing this resource. The instructor has been notified.
"; + #notify author + &Apache::lonmsg::author_res_msg($ENV{'request.filename'},$_[0]); + #notify course + if ( $ENV{'request.course.id'} ) { + my $users=$ENV{'course.'.$ENV{'request.course.id'}.'.comment.email'}; + foreach my $user (split /\,/, $users) { + ($user,my $domain) = split /:/, $user; + &Apache::lonmsg::user_normal_msg($user,$domain,"Error in $ENV{'request.filename'}",$_[0]); + } + } + + #FIXME probably shouldn't have me get everything forever. + &Apache::lonmsg::user_normal_msg('albertel','msu',"Error in $ENV{'request.filename'}",$_[0]); + #&Apache::lonmsg::user_normal_msg('albertel','103',"Error in $ENV{'request.filename'}",$_[0]); + } +} + +sub warning { + if ($ENV{'request.state'} eq 'construct') { + print "WARNING:".$_[0]."
\n"; + } +} + +sub get_param { + my ($param,$parstack,$safeeval,$context) = @_; + if ( ! $context ) { $context = -1; } + my $args =''; + if ( $#$parstack > (-2-$context) ) { $args=$$parstack[$context]; } + return &Apache::run::run("{$args;".'return $'.$param.'}',$safeeval); #' +} + +sub register_insert { + my @data = split /\n/, &Apache::lonnet::getfile('/home/httpd/lonTabs/insertlist.tab'); + my $i; + my $tagnum=0; + my @order; + for ($i=0;$i < $#data; $i++) { + my $line = $data[$i]; + if ( $line =~ /^\#/ || $line =~ /^\s*\n/) { next; } + if ( $line =~ /TABLE/ ) { last; } + my ($tag,$descrip,$function,$show) = split(/,/, $line); + $insertlist{"$tagnum.tag"} = $tag; + $insertlist{"$tagnum.description"} = $descrip; + $insertlist{"$tagnum.function"} = $function; + $insertlist{"$tagnum.show"}= $show; + $tagnum++; + } + $i++; #skipping TABLE line + $tagnum = 0; + for (;$i < $#data;$i++) { + my $line = $data[$i]; + my ($mnemonic,@which) = split(/ +/,$line); + my $tag = $insertlist{"$tagnum.tag"}; + for (my $j=0;$j <$#which;$j++) { + if ( $which[$j] eq 'Y' ) { + if ($insertlist{"$j.show"} ne 'no') { + push(@{ $insertlist{"$tag.which"} },$j); + } + } + } + $tagnum++; + } +} 1; __END__ + + 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.