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

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

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