File:  [LON-CAPA] / loncom / xml / lonxml.pm
Revision 1.79: download - view: text, annotated - select for diffs
Sat May 26 17:27:28 2001 UTC (23 years ago) by www
Branches: MAIN
CVS tags: HEAD
Simple Editor works

    1: # The LearningOnline Network with CAPA
    2: # XML Parser Module 
    3: #
    4: # last modified 06/26/00 by Alexander Sakharuk
    5: # 11/6 Gerd Kortemeyer
    6: # 6/1/1 Gerd Kortemeyer
    7: # 2/21,3/13 Guy
    8: # 3/29,5/4 Gerd Kortemeyer
    9: # 5/10 Scott Harrison
   10: # 5/26 Gerd Kortemeyer
   11: 
   12: package Apache::lonxml; 
   13: use vars 
   14: qw(@pwd @outputstack $redirection $import @extlinks $metamode $evaluate %insertlist @namespace);
   15: use strict;
   16: use HTML::TokeParser;
   17: use Safe;
   18: use Safe::Hole;
   19: use Opcode;
   20: 
   21: sub register {
   22:   my $space;
   23:   my @taglist;
   24:   my $temptag;
   25:   ($space,@taglist) = @_;
   26:   foreach $temptag (@taglist) {
   27:     $Apache::lonxml::alltags{$temptag}=$space;
   28:   }
   29: }
   30: 
   31: use Apache::Constants qw(:common);
   32: use Apache::lontexconvert;
   33: use Apache::style;
   34: use Apache::run;
   35: use Apache::londefdef;
   36: use Apache::scripttag;
   37: use Apache::edit;
   38: use Apache::lonnet;
   39: use Apache::File;
   40: 
   41: #==================================================   Main subroutine: xmlparse  
   42: #debugging control, to turn on debugging modify the correct handler
   43: $Apache::lonxml::debug=0;
   44: 
   45: #path to the directory containing the file currently being processed
   46: @pwd=();
   47: 
   48: #these two are used for capturing a subset of the output for later processing,
   49: #don't touch them directly use &startredirection and &endredirection
   50: @outputstack = ();
   51: $redirection = 0;
   52: 
   53: #controls wheter the <import> tag actually does
   54: $import = 1;
   55: @extlinks=();
   56: 
   57: # meta mode is a bit weird only some output is to be turned off
   58: #<output> tag turns metamode off (defined in londefdef.pm)
   59: $metamode = 0;
   60: 
   61: # turns on and of run::evaluate actually derefencing var refs
   62: $evaluate = 1;
   63: 
   64: # data structure for eidt mode, determines what tags can go into what other tags
   65: %insertlist=();
   66: 
   67: #stores the list of active tag namespaces
   68: @namespace=();
   69: 
   70: sub xmlbegin {
   71:   my $output='';
   72:   if ($ENV{'browser.mathml'}) {
   73:       $output='<?xml version="1.0"?>'
   74:             .'<?xml-stylesheet type="text/css" href="/adm/MathML/mathml.css"?>'
   75:             .'<!DOCTYPE html SYSTEM "/adm/MathML/mathml.dtd" '
   76:             .'[<!ENTITY mathns "http://www.w3.org/1998/Math/MathML">]>'
   77:             .'<html xmlns:math="http://www.w3.org/1998/Math/MathML" ' 
   78: 		.'xmlns="http://www.w3.org/TR/REC-html40">';
   79:   } else {
   80:       $output='<html>';
   81:   }
   82:   return $output;
   83: }
   84: 
   85: sub xmlend {
   86:     return '</html>';
   87: }
   88: 
   89: sub fontsettings() {
   90:     my $headerstring='';
   91:     if (($ENV{'browser.os'} eq 'mac') && (!$ENV{'browser.mathml'})) { 
   92:          $headerstring.=
   93:              '<meta Content-Type="text/html; charset=x-mac-roman">';
   94:     }
   95:     return $headerstring;
   96: }
   97: 
   98: sub registerurl {
   99:   return (<<ENDSCRIPT);
  100: <script language="JavaScript">
  101: // BEGIN LON-CAPA Internal
  102:     function LONCAPAreg() {
  103:        if (window.location.pathname!="/res/adm/pages/menu.html") {
  104: 	  menu=window.open("","LONCAPAmenu");
  105: 	  menu.currentURL=window.location.pathname;
  106:           menu.currentStale=0;
  107:        }
  108:     }
  109:   
  110:     function LONCAPAstale() {
  111:        if (window.location.pathname!="/res/adm/pages/menu.html") {
  112: 	  menu=window.open("","LONCAPAmenu");
  113:           menu.currentStale=1;
  114:        }
  115:     }
  116: // END LON-CAPA Internal
  117: </script>
  118: ENDSCRIPT
  119: }
  120: 
  121: sub loadevents() {
  122:     return 'LONCAPAreg();';
  123: }
  124: 
  125: sub unloadevents() {
  126:     return 'LONCAPAstale();';
  127: }
  128: 
  129: sub printalltags {
  130:   my $temp;
  131:   foreach $temp (sort keys %Apache::lonxml::alltags) {
  132:     &Apache::lonxml::debug("$temp -- $Apache::lonxml::alltags{$temp}");
  133:   }
  134: }
  135: 
  136: sub xmlparse {
  137: 
  138:  my ($target,$content_file_string,$safeinit,%style_for_target) = @_;
  139:  if ($target eq 'meta') {
  140:    $Apache::lonxml::redirection = 0;
  141:    $Apache::lonxml::metamode = 1;
  142:    $Apache::lonxml::evaluate = 1;
  143:    $Apache::lonxml::import = 0;
  144:  } elsif ($target eq 'grade') {
  145:    &startredirection;
  146:    $Apache::lonxml::metamode = 0;
  147:    $Apache::lonxml::evaluate = 1;
  148:    $Apache::lonxml::import = 1;
  149:  } elsif ($target eq 'modified') {
  150:    $Apache::lonxml::redirection = 0;
  151:    $Apache::lonxml::metamode = 0;
  152:    $Apache::lonxml::evaluate = 0;
  153:    $Apache::lonxml::import = 0;
  154:  } else {
  155:    $Apache::lonxml::redirection = 0;
  156:    $Apache::lonxml::metamode = 0;
  157:    $Apache::lonxml::evaluate = 1;
  158:    $Apache::lonxml::import = 1;
  159:  }
  160:  #&printalltags();
  161:  my @pars = ();
  162:  @Apache::lonxml::pwd=();
  163:  my $pwd=$ENV{'request.filename'};
  164:  $pwd =~ s:/[^/]*$::;
  165:  &newparser(\@pars,\$content_file_string,$pwd);
  166:  my $currentstring = '';
  167:  my $finaloutput = ''; 
  168:  my $newarg = '';
  169:  my $result;
  170: 
  171:  my $safeeval = new Safe;
  172:  my $safehole = new Safe::Hole;
  173:  $safeeval->permit("entereval");
  174:  $safeeval->permit(":base_math");
  175:  $safeeval->permit("sort");
  176:  $safeeval->deny(":base_io");
  177:  $safehole->wrap(\&Apache::lonnet::EXT,$safeeval,'&EXT');
  178: #need to inspect this class of ops
  179: # $safeeval->deny(":base_orig");
  180:  $safeinit .= ';$external::target='.$target.';';
  181:  $safeinit .= ';$external::randomseed='.&Apache::lonnet::rndseed().';';
  182:  &Apache::run::run($safeinit,$safeeval);
  183: #-------------------- Redefinition of the target in the case of compound target
  184: 
  185:  ($target, my @tenta) = split('&&',$target);
  186: 
  187:  my @stack = (); 
  188:  my @parstack = ();
  189:  &initdepth;
  190:  my $token;
  191:  while ( $#pars > -1 ) {
  192:    while ($token = $pars[$#pars]->get_token) {
  193:      if (($token->[0] eq 'T') || ($token->[0] eq 'C') || ($token->[0] eq 'D') ) {
  194:        if ($metamode<1) { $result=$token->[1]; }
  195:      } elsif ($token->[0] eq 'PI') {
  196:        if ($metamode<1) { $result=$token->[2]; }
  197:      } elsif ($token->[0] eq 'S') {
  198:        # add tag to stack 	    
  199:        push (@stack,$token->[1]);
  200:        # add parameters list to another stack
  201:        push (@parstack,&parstring($token));
  202:        &increasedepth($token);       
  203:        if (exists $style_for_target{$token->[1]}) {
  204: 	 if ($Apache::lonxml::redirection) {
  205: 	   $Apache::lonxml::outputstack['-1'] .=  
  206: 	     &recurse($style_for_target{$token->[1]},$target,$safeeval,
  207: 		      \%style_for_target,@parstack);
  208: 	 } else {
  209: 	   $finaloutput .= &recurse($style_for_target{$token->[1]},$target,
  210: 				    $safeeval,\%style_for_target,@parstack);
  211: 	 }
  212:        } else {
  213: 	 $result = &callsub("start_$token->[1]", $target, $token,\@parstack,
  214: 			    \@pars, $safeeval, \%style_for_target);
  215:        }              
  216:      } elsif ($token->[0] eq 'E')  {
  217:        #clear out any tags that didn't end
  218:        while ($token->[1] ne $stack[$#stack] && ($#stack > -1)) {
  219: 	 &Apache::lonxml::warning("Unbalanced tags in resource $stack['-1']");
  220: 	 pop @stack;pop @parstack;&decreasedepth($token);
  221:        }
  222:        
  223:        if (exists $style_for_target{'/'."$token->[1]"}) {
  224: 	 if ($Apache::lonxml::redirection) {
  225: 	   $Apache::lonxml::outputstack['-1'] .=  
  226: 	     &recurse($style_for_target{'/'."$token->[1]"},
  227: 		      $target,$safeeval,\%style_for_target,@parstack);
  228: 	 } else {
  229: 	   $finaloutput .= &recurse($style_for_target{'/'."$token->[1]"},
  230: 				    $target,$safeeval,\%style_for_target,
  231: 				    @parstack);
  232: 	 }
  233: 
  234:        } else {
  235: 	 $result = &callsub("end_$token->[1]", $target, $token, \@parstack,
  236: 			    \@pars,$safeeval, \%style_for_target);
  237:        }
  238:      } else {
  239:        &Apache::lonxml::error("Unknown token event :$token->[0]:$token->[1]:");
  240:      }
  241:      #evaluate variable refs in result
  242:      if ($result ne "") {
  243:        if ( $#parstack > -1 ) {
  244: 	 if ($Apache::lonxml::redirection) {
  245: 	   $Apache::lonxml::outputstack['-1'] .= 
  246: 	     &Apache::run::evaluate($result,$safeeval,$parstack[$#parstack]);
  247: 	 } else {
  248: 	   $finaloutput .= &Apache::run::evaluate($result,$safeeval,
  249: 						  $parstack[$#parstack]);
  250: 	 }
  251:        } else {
  252: 	 $finaloutput .= &Apache::run::evaluate($result,$safeeval,'');
  253:        }
  254:        $result = '';
  255:      } 
  256:      if ($token->[0] eq 'E') { 
  257:        pop @stack;pop @parstack;&decreasedepth($token);
  258:      }
  259:    }
  260:    pop @pars;
  261:    pop @Apache::lonxml::pwd;
  262:  }
  263: 
  264: # if ($target eq 'meta') {
  265: #   $finaloutput.=&endredirection;
  266: # }
  267: 
  268:   if (($ENV{'QUERY_STRING'}) && ($target eq 'web')) {
  269:       $finaloutput=&afterburn($finaloutput);
  270:   }
  271: 
  272:  return $finaloutput;
  273: }
  274: 
  275: 
  276: sub recurse {
  277:   
  278:   my @innerstack = (); 
  279:   my @innerparstack = ();
  280:   my ($newarg,$target,$safeeval,$style_for_target,@parstack) = @_;
  281:   my @pat = ();
  282:   &newparser(\@pat,\$newarg);
  283:   my $tokenpat;
  284:   my $partstring = '';
  285:   my $output='';
  286:   my $decls='';
  287:   while ( $#pat > -1 ) {
  288:     while  ($tokenpat = $pat[$#pat]->get_token) {
  289:       if (($tokenpat->[0] eq 'T') || ($tokenpat->[0] eq 'C') || ($tokenpat->[0] eq 'D') ) {
  290: 	if ($metamode<1) { $partstring=$tokenpat->[1]; }
  291:       } elsif ($tokenpat->[0] eq 'PI') {
  292: 	if ($metamode<1) { $partstring=$tokenpat->[2]; }
  293:       } elsif ($tokenpat->[0] eq 'S') {
  294: 	push (@innerstack,$tokenpat->[1]);
  295: 	push (@innerparstack,&parstring($tokenpat));
  296: 	&increasedepth($tokenpat);
  297: 	$partstring = &callsub("start_$tokenpat->[1]", 
  298: 			       $target, $tokenpat, \@innerparstack,
  299: 			       \@pat, $safeeval, $style_for_target);
  300:       } elsif ($tokenpat->[0] eq 'E') {
  301: 	#clear out any tags that didn't end
  302: 	while ($tokenpat->[1] ne $innerstack[$#innerstack] 
  303: 	       && ($#innerstack > -1)) {
  304: 	  &Apache::lonxml::warning("Unbalanced tags in resource $innerstack['-1']");
  305: 	  pop @innerstack;pop @innerparstack;&decreasedepth($tokenpat);
  306: 	}
  307: 	$partstring = &callsub("end_$tokenpat->[1]",
  308: 			       $target, $tokenpat, \@innerparstack,
  309: 			       \@pat, $safeeval, $style_for_target);
  310:       } else {
  311: 	&Apache::lonxml::error("Unknown token event :$tokenpat->[0]:$tokenpat->[1]:");
  312:       }
  313:       #pass both the variable to the style tag, and the tag we 
  314:       #are processing inside the <definedtag>
  315:       if ( $partstring ne "" ) {
  316: 	if ( $#parstack > -1 ) { 
  317: 	  if ( $#innerparstack > -1 ) { 
  318: 	    $decls= $parstack[$#parstack].$innerparstack[$#innerparstack];
  319: 	  } else {
  320: 	    $decls= $parstack[$#parstack];
  321: 	  }
  322: 	} else {
  323: 	  if ( $#innerparstack > -1 ) { 
  324: 	    $decls=$innerparstack[$#innerparstack];
  325: 	  } else {
  326: 	    $decls='';
  327: 	  }
  328: 	}
  329: 	$output .= &Apache::run::evaluate($partstring,$safeeval,$decls);
  330: 	$partstring = '';
  331:       }
  332:       if ($tokenpat->[0] eq 'E') { pop @innerstack;pop @innerparstack;
  333: 				 &decreasedepth($tokenpat);}
  334:     }
  335:     pop @pat;
  336:     pop @Apache::lonxml::pwd;
  337:   }
  338:   return $output;
  339: }
  340: 
  341: sub callsub {
  342:   my ($sub,$target,$token,$parstack,$parser,$safeeval,$style)=@_;
  343:   my $currentstring='';
  344:   my $nodefault;
  345:   {
  346:     my $sub1;
  347:     no strict 'refs';
  348:     if ($target eq 'edit' && $token->[0] eq 'S') {
  349:       $currentstring = &Apache::edit::tag_start($target,$token,$parstack,$parser,
  350: 						$safeeval,$style);
  351:     }
  352:     my $tag=$token->[1];
  353:     my $space=$Apache::lonxml::alltags{$tag};
  354:     if (!$space) {
  355: 	$tag=~tr/A-Z/a-z/;
  356: 	$sub=~tr/A-Z/a-z/;
  357: 	$space=$Apache::lonxml::alltags{$tag}
  358:     }
  359:     if ($space) {
  360:       #&Apache::lonxml::debug("Calling sub $sub in $space $metamode<br />\n");
  361:       $sub1="$space\:\:$sub";
  362:       $Apache::lonxml::curdepth=join('_',@Apache::lonxml::depthcounter);
  363:       ($currentstring,$nodefault) = &$sub1($target,$token,$parstack,$parser,
  364: 					   $safeeval,$style);
  365:     } else {
  366:       #&Apache::lonxml::debug("NOT Calling sub $sub in $space $metamode<br />\n");
  367:       if ($metamode <1) {
  368: 	if (defined($token->[4]) && ($metamode < 1)) {
  369: 	  $currentstring = $token->[4];
  370: 	} else {
  371: 	  $currentstring = $token->[2];
  372: 	}
  373:       }
  374:     }
  375:     &Apache::lonxml::debug("nodefalt:$nodefault:");
  376:     if ($currentstring eq '' && $nodefault eq '') {
  377:       if ($target eq 'edit') {
  378: 	&Apache::lonxml::debug("doing default edit for $token->[1]");
  379: 	if ($token->[0] eq 'S') {
  380: 	  $currentstring = &Apache::edit::tag_start($target,$token);
  381: 	} elsif ($token->[0] eq 'E') {
  382: 	  $currentstring = &Apache::edit::tag_end($target,$token);
  383: 	}
  384:       } elsif ($target eq 'modified') {
  385: 	if ($token->[0] eq 'S') {
  386: 	  $currentstring = $token->[4];
  387: 	  $currentstring.=&Apache::edit::handle_insert();
  388: 	} else {
  389: 	  $currentstring = $token->[2];
  390: 	}
  391:       }
  392:     }
  393:     use strict 'refs';
  394:   }
  395:   return $currentstring;
  396: }
  397: 
  398: sub startredirection {
  399:   $Apache::lonxml::redirection++;
  400:   push (@Apache::lonxml::outputstack, '');
  401: }
  402: 
  403: sub endredirection {
  404:   if (!$Apache::lonxml::redirection) {
  405:     &Apache::lonxml::error("Endredirection was called, before a startredirection, perhaps you have unbalanced tags. Some debuging information:".join ":",caller);
  406:     return '';
  407:   }
  408:   $Apache::lonxml::redirection--;
  409:   pop @Apache::lonxml::outputstack;
  410: }
  411: 
  412: sub initdepth {
  413:   @Apache::lonxml::depthcounter=();
  414:   $Apache::lonxml::depth=-1;
  415:   $Apache::lonxml::olddepth=-1;
  416: }
  417: 
  418: sub increasedepth {
  419:   my ($token) = @_;
  420:   $Apache::lonxml::depth++;
  421:   $Apache::lonxml::depthcounter[$Apache::lonxml::depth]++;
  422:   if ($Apache::lonxml::depthcounter[$Apache::lonxml::depth]==1) {
  423:     $Apache::lonxml::olddepth=$Apache::lonxml::depth;
  424:   }
  425:   my $curdepth=join('_',@Apache::lonxml::depthcounter);
  426:   &Apache::lonxml::debug("s $Apache::lonxml::depth : $Apache::lonxml::olddepth : $curdepth : $token->[1]\n");
  427: #print "<br />s $Apache::lonxml::depth : $Apache::lonxml::olddepth : $curdepth : $token->[1]\n";
  428: }
  429: 
  430: sub decreasedepth {
  431:   my ($token) = @_;
  432:   $Apache::lonxml::depth--;
  433:   if ($Apache::lonxml::depth<$Apache::lonxml::olddepth-1) {
  434:     $#Apache::lonxml::depthcounter--;
  435:     $Apache::lonxml::olddepth=$Apache::lonxml::depth+1;
  436:   }
  437:   if (  $Apache::lonxml::depth < -1) {
  438:     &Apache::lonxml::warning("Unbalanced tags in resource");   
  439:     $Apache::lonxml::depth='-1';
  440:   }
  441:   my $curdepth=join('_',@Apache::lonxml::depthcounter);
  442:   &Apache::lonxml::debug("e $Apache::lonxml::depth : $Apache::lonxml::olddepth : $token->[1] : $curdepth\n");
  443: #print "<br />e $Apache::lonxml::depth : $Apache::lonxml::olddepth : $token->[1] : $curdepth\n";
  444: }
  445: 
  446: sub get_all_text {
  447: 
  448:  my($tag,$pars)= @_;
  449:  my $depth=0;
  450:  my $token;
  451:  my $result='';
  452:  if ( $tag =~ m:^/: ) { 
  453:    my $tag=substr($tag,1); 
  454: #   &Apache::lonxml::debug("have:$tag:");
  455:    while (($depth >=0) && ($token = $pars->get_token)) {
  456: #     &Apache::lonxml::debug("e token:$token->[0]:$depth:$token->[1]");
  457:      if (($token->[0] eq 'T')||($token->[0] eq 'C')||($token->[0] eq 'D')) {
  458:        $result.=$token->[1];
  459:      } elsif ($token->[0] eq 'PI') {
  460:        $result.=$token->[2];
  461:      } elsif ($token->[0] eq 'S') {
  462:        if ($token->[1] eq $tag) { $depth++; }
  463:        $result.=$token->[4];
  464:      } elsif ($token->[0] eq 'E')  {
  465:        if ( $token->[1] eq $tag) { $depth--; }
  466:        #skip sending back the last end tag
  467:        if ($depth > -1) { $result.=$token->[2]; } else {
  468: 	 $pars->unget_token($token);
  469:        }
  470:      }
  471:    }
  472:  } else {
  473:    while ($token = $pars->get_token) {
  474: #     &Apache::lonxml::debug("s token:$token->[0]:$depth:$token->[1]");
  475:      if (($token->[0] eq 'T')||($token->[0] eq 'C')||($token->[0] eq 'D')) {
  476:        $result.=$token->[1];
  477:      } elsif ($token->[0] eq 'PI') {
  478:        $result.=$token->[2];
  479:      } elsif ($token->[0] eq 'S') {
  480:        if ( $token->[1] eq $tag) { 
  481: 	 $pars->unget_token($token); last;
  482:        } else {
  483: 	 $result.=$token->[4];
  484:        }
  485:      } elsif ($token->[0] eq 'E')  {
  486:        $result.=$token->[2];
  487:      }
  488:    }
  489:  }
  490: # &Apache::lonxml::debug("Exit:$result:");
  491:  return $result
  492: }
  493: 
  494: sub newparser {
  495:   my ($parser,$contentref,$dir) = @_;
  496:   push (@$parser,HTML::TokeParser->new($contentref));
  497:   $$parser['-1']->xml_mode('1');
  498:   if ( $dir eq '' ) {
  499:     push (@Apache::lonxml::pwd, $Apache::lonxml::pwd[$#Apache::lonxml::pwd]);
  500:   } else {
  501:     push (@Apache::lonxml::pwd, $dir);
  502:   } 
  503: #  &Apache::lonxml::debug("pwd:$#Apache::lonxml::pwd");
  504: #  &Apache::lonxml::debug("pwd:$Apache::lonxml::pwd[$#Apache::lonxml::pwd]");
  505: }
  506: 
  507: sub parstring {
  508:   my ($token) = @_;
  509:   my $temp='';
  510:   map {
  511:     unless ($_=~/\W/) {
  512:       my $val=$token->[2]->{$_};
  513:       $val =~ s/([\%\@\\])/\\$1/g;
  514:       #if ($val =~ m/^[\%\@]/) { $val="\\".$val; }
  515:       $temp .= "my \$$_=\"$val\";"
  516:     }
  517:   } @{$token->[3]};
  518:   return $temp;
  519: }
  520: 
  521: sub writeallows {
  522:     my $thisurl='/res/'.&Apache::lonnet::declutter(shift);
  523:     my $thisdir=$thisurl;
  524:     $thisdir=~s/\/[^\/]+$//;
  525:     my %httpref=();
  526:     map {
  527:        $httpref{'httpref.'.
  528:  	        &Apache::lonnet::hreflocation($thisdir,$_)}=$thisurl;              } @extlinks;
  529:     &Apache::lonnet::appenv(%httpref);
  530: }
  531: 
  532: #
  533: # Afterburner handles anchors, highlights and links
  534: #
  535: sub afterburn {
  536:     my $result=shift;
  537:     map {
  538:        my ($name, $value) = split(/=/,$_);
  539:        $value =~ tr/+/ /;
  540:        $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
  541:        if (($name eq 'highlight')||($name eq 'anchor')||($name eq 'link')) {
  542:            unless ($ENV{'form.'.$name}) {
  543:               $ENV{'form.'.$name}=$value;
  544: 	   }
  545:        }
  546:     } (split(/&/,$ENV{'QUERY_STRING'}));
  547:     if ($ENV{'form.highlight'}) {
  548:         map {
  549:            my $anchorname=$_;
  550: 	   my $matchthis=$anchorname;
  551:            $matchthis=~s/\_+/\\s\+/g;
  552:            $result=~s/($matchthis)/\<font color=\"red\"\>$1\<\/font\>/gs;
  553:        } split(/\,/,$ENV{'form.highlight'});
  554:     }
  555:     if ($ENV{'form.link'}) {
  556:         map {
  557:            my ($anchorname,$linkurl)=split(/\>/,$_);
  558: 	   my $matchthis=$anchorname;
  559:            $matchthis=~s/\_+/\\s\+/g;
  560:            $result=~s/($matchthis)/\<a href=\"$linkurl\"\>$1\<\/a\>/gs;
  561:        } split(/\,/,$ENV{'form.link'});
  562:     }
  563:     if ($ENV{'form.anchor'}) {
  564:         my $anchorname=$ENV{'form.anchor'};
  565: 	my $matchthis=$anchorname;
  566:         $matchthis=~s/\_+/\\s\+/g;
  567:         $result=~s/($matchthis)/\<a name=\"$anchorname\"\>$1\<\/a\>/s;
  568:         $result.=(<<"ENDSCRIPT");
  569: <script>
  570:     document.location.hash='$anchorname';
  571: </script>
  572: ENDSCRIPT
  573:     }
  574:     return $result;
  575: }
  576: 
  577: sub storefile {
  578:     my ($file,$contents)=@_;
  579:     if (my $fh=Apache::File->new('>'.$file)) {
  580: 	print $fh $contents;
  581:         $fh->close();
  582:     }
  583: }
  584: 
  585: sub inserteditinfo {
  586:       my ($result,$filecontents)=@_;
  587:       unless ($filecontents) {
  588: 	  $filecontents=(<<SIMPLECONTENT);
  589: <html>
  590: <head>
  591: <title>
  592:                            Title of Document Goes Here
  593: </title>
  594: </head>
  595: <body bgcolor="#FFFFFF">
  596: 
  597:                            Body of Document Goes Here
  598: 
  599: </body>
  600: </html>
  601: SIMPLECONTENT
  602:       }
  603:       my $editheader='<a href="#editsection">Edit below</a><hr />';
  604:       my $editfooter=(<<ENDFOOTER);
  605: <hr />
  606: <a name="editsection" />
  607: <form method="post">
  608: <textarea cols="80" rows="40" name="filecont">$filecontents</textarea>
  609: <br />
  610: <input type="submit" name="savethisfile" value="Save this file" />
  611: </form>
  612: ENDFOOTER
  613:       $result=~s/(\<body[^\>]*\>)/$1$editheader/is;
  614:       $result=~s/(\<\/body\>)/$editfooter/is;
  615:       return $result;
  616: }
  617: 
  618: sub handler {
  619:   my $request=shift;
  620: 
  621:   my $target='web';
  622: 
  623:   $Apache::lonxml::debug=0;
  624: 
  625:   if ($ENV{'browser.mathml'}) {
  626:     $request->content_type('text/xml');
  627:   } else {
  628:     $request->content_type('text/html');
  629:   }
  630:   
  631:   $request->send_http_header;
  632:   
  633:   return OK if $request->header_only;
  634: 
  635: 
  636:   my $file=&Apache::lonnet::filelocation("",$request->uri);
  637: #
  638: # Edit action? Save file.
  639: #
  640:   unless ($ENV{'request.state'} eq 'published') {
  641:       if ($ENV{'form.savethisfile'}) {
  642: 	  &storefile($file,$ENV{'form.filecont'});
  643:       }
  644:   }
  645:   my %mystyle;
  646:   my $result = ''; 
  647:   my $filecontents=&Apache::lonnet::getfile($file);
  648:   if ($filecontents == -1) {
  649:     $result=(<<ENDNOTFOUND);
  650: <html>
  651: <head>
  652: <title>File not found</title>
  653: </head>
  654: <body bgcolor="#FFFFFF">
  655: <b>File not found: $file</b>
  656: </body>
  657: </html>
  658: ENDNOTFOUND
  659:     $filecontents='';
  660:   } else {
  661:     $result = &Apache::lonxml::xmlparse($target,$filecontents,'',%mystyle);
  662:   }
  663: 
  664: #
  665: # Edit action? Insert editing commands
  666: #
  667:   unless ($ENV{'request.state'} eq 'published') {
  668:       $result=&inserteditinfo($result,$filecontents);
  669:   }
  670: 
  671:   $request->print($result);
  672: 
  673:   writeallows($request->uri);
  674:   return OK;
  675: }
  676:  
  677: sub debug {
  678:   if ($Apache::lonxml::debug eq 1) {
  679:     print "DEBUG:".$_[0]."<br />\n";
  680:   }
  681: }
  682: 
  683: sub error {
  684:   if (($Apache::lonxml::debug eq 1) || ($ENV{'request.state'} eq 'construct') ) {
  685:     print "<b>ERROR:</b>".$_[0]."<br />\n";
  686:   } else {
  687:     print "<b>An Error occured while processing this resource. The instructor has been notified.</b> <br />";
  688:     #notify author
  689:     &Apache::lonmsg::author_res_msg($ENV{'request.filename'},$_[0]);
  690:     #notify course
  691:     if ( $ENV{'request.course.id'} ) {
  692:       my $users=$ENV{'course.'.$ENV{'request.course.id'}.'.comment.email'};
  693:       foreach my $user (split /\,/, $users) {
  694: 	($user,my $domain) = split /:/, $user;
  695: 	&Apache::lonmsg::user_normal_msg($user,$domain,"Error in $ENV{'request.filename'}",$_[0]);
  696:       }
  697:     }
  698: 
  699:     #FIXME probably shouldn't have me get everything forever.
  700:     &Apache::lonmsg::user_normal_msg('albertel','msu',"Error in $ENV{'request.filename'}",$_[0]);
  701:     #&Apache::lonmsg::user_normal_msg('albertel','103',"Error in $ENV{'request.filename'}",$_[0]);
  702:   }
  703: }
  704: 
  705: sub warning {
  706:   if ($ENV{'request.state'} eq 'construct') {
  707:     print "<b>W</b>ARNING<b>:</b>".$_[0]."<br />\n";
  708:   }
  709: }
  710: 
  711: sub register_insert {
  712:   my @data = split /\n/, &Apache::lonnet::getfile('/home/httpd/lonTabs/insertlist.tab');
  713:   my $i;
  714:   my $tagnum=0;
  715:   my @order;
  716:   for ($i=0;$i < $#data; $i++) {
  717:     my $line = $data[$i];
  718:     if ( $line =~ /^\#/ || $line =~ /^\s*\n/) { next; }
  719:     if ( $line =~ /TABLE/ ) { last; }
  720:     my ($tag,$descrip,$function,$show) = split(/,/, $line);
  721:     $insertlist{"$tagnum.tag"} = $tag;
  722:     $insertlist{"$tagnum.description"} = $descrip;
  723:     $insertlist{"$tagnum.function"} = $function;
  724:     $insertlist{"$tagnum.show"}= $show;
  725:     $tagnum++;
  726:   }
  727:   $i++; #skipping TABLE line
  728:   $tagnum = 0;
  729:   for (;$i < $#data;$i++) {
  730:     my $line = $data[$i];
  731:     my ($mnemonic,@which) = split(/ +/,$line);
  732:     my $tag = $insertlist{"$tagnum.tag"};
  733:     for (my $j=0;$j <$#which;$j++) {
  734:       if ( $which[$j] eq 'Y' ) {
  735: 	if ($insertlist{"$j.show"} ne 'no') {
  736: 	  push(@{ $insertlist{"$tag.which"} },$j);
  737: 	}
  738:       }
  739:     }
  740:     $tagnum++;
  741:   }
  742: }
  743: 1;
  744: __END__
  745: 
  746: 

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