![]() ![]() | ![]() |
Bug #5081. Adds undo function to edit HTML.
1: # The LearningOnline Network with CAPA 2: # XML Parser Module 3: # 4: # $Id: lonxml.pm,v 1.428 2006/11/30 01:07:09 banghart Exp $ 5: # 6: # Copyright Michigan State University Board of Trustees 7: # 8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA). 9: # 10: # LON-CAPA is free software; you can redistribute it and/or modify 11: # it under the terms of the GNU General Public License as published by 12: # the Free Software Foundation; either version 2 of the License, or 13: # (at your option) any later version. 14: # 15: # LON-CAPA is distributed in the hope that it will be useful, 16: # but WITHOUT ANY WARRANTY; without even the implied warranty of 17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18: # GNU General Public License for more details. 19: # 20: # You should have received a copy of the GNU General Public License 21: # along with LON-CAPA; if not, write to the Free Software 22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23: # 24: # /home/httpd/html/adm/gpl.txt 25: # 26: # http://www.lon-capa.org/ 27: # 28: # Copyright for TtHfunc and TtMfunc by Ian Hutchinson. 29: # TtHfunc and TtMfunc (the "Code") may be compiled and linked into 30: # binary executable programs or libraries distributed by the 31: # Michigan State University (the "Licensee"), but any binaries so 32: # distributed are hereby licensed only for use in the context 33: # of a program or computational system for which the Licensee is the 34: # primary author or distributor, and which performs substantial 35: # additional tasks beyond the translation of (La)TeX into HTML. 36: # The C source of the Code may not be distributed by the Licensee 37: # to any other parties under any circumstances. 38: # 39: 40: 41: package Apache::lonxml; 42: use vars 43: qw(@pwd @outputstack $redirection $import @extlinks $metamode $evaluate %insertlist @namespace $errorcount $warningcount); 44: use strict; 45: use HTML::LCParser(); 46: use HTML::TreeBuilder(); 47: use HTML::Entities(); 48: use Safe(); 49: use Safe::Hole(); 50: use Math::Cephes(); 51: use Math::Random(); 52: use Opcode(); 53: use POSIX qw(strftime); 54: use Time::HiRes qw( gettimeofday tv_interval ); 55: use Symbol(); 56: 57: sub register { 58: my ($space,@taglist) = @_; 59: foreach my $temptag (@taglist) { 60: push(@{ $Apache::lonxml::alltags{$temptag} },$space); 61: } 62: } 63: 64: sub deregister { 65: my ($space,@taglist) = @_; 66: foreach my $temptag (@taglist) { 67: my $tempspace = $Apache::lonxml::alltags{$temptag}[-1]; 68: if ($tempspace eq $space) { 69: pop(@{ $Apache::lonxml::alltags{$temptag} }); 70: } 71: } 72: #&printalltags(); 73: } 74: 75: use Apache::Constants qw(:common); 76: use Apache::lontexconvert(); 77: use Apache::style(); 78: use Apache::run(); 79: use Apache::londefdef(); 80: use Apache::scripttag(); 81: use Apache::languagetags(); 82: use Apache::edit(); 83: use Apache::inputtags(); 84: use Apache::outputtags(); 85: use Apache::lonnet; 86: use Apache::File(); 87: use Apache::loncommon(); 88: use Apache::lonfeedback(); 89: use Apache::lonmsg(); 90: use Apache::loncacc(); 91: use Apache::lonlocal; 92: 93: #================================================== Main subroutine: xmlparse 94: #debugging control, to turn on debugging modify the correct handler 95: $Apache::lonxml::debug=0; 96: 97: # keeps count of the number of warnings and errors generated in a parse 98: $warningcount=0; 99: $errorcount=0; 100: 101: #path to the directory containing the file currently being processed 102: @pwd=(); 103: 104: #these two are used for capturing a subset of the output for later processing, 105: #don't touch them directly use &startredirection and &endredirection 106: @outputstack = (); 107: $redirection = 0; 108: 109: #controls wheter the <import> tag actually does 110: $import = 1; 111: @extlinks=(); 112: 113: # meta mode is a bit weird only some output is to be turned off 114: #<output> tag turns metamode off (defined in londefdef.pm) 115: $metamode = 0; 116: 117: # turns on and of run::evaluate actually derefencing var refs 118: $evaluate = 1; 119: 120: # data structure for eidt mode, determines what tags can go into what other tags 121: %insertlist=(); 122: 123: # stores the list of active tag namespaces 124: @namespace=(); 125: 126: # a pointer the the Apache request object 127: $Apache::lonxml::request=''; 128: 129: # a problem number counter, and check on ether it is used 130: $Apache::lonxml::counter=1; 131: $Apache::lonxml::counter_changed=0; 132: 133: #internal check on whether to look at style defs 134: $Apache::lonxml::usestyle=1; 135: 136: #locations used to store the parameter string for style substitutions 137: $Apache::lonxml::style_values=''; 138: $Apache::lonxml::style_end_values=''; 139: 140: #array of ssi calls that need to occur after we are done parsing 141: @Apache::lonxml::ssi_info=(); 142: 143: #should we do the postag variable interpolation 144: $Apache::lonxml::post_evaluate=1; 145: 146: #a header message to emit in the case of any generated warning or errors 147: $Apache::lonxml::warnings_error_header=''; 148: 149: # Control whether or not LaTeX symbols should be substituted for their 150: # \ style equivalents...this may be turned off e.g. in an verbatim 151: # environment. 152: 153: $Apache::lonxml::substitute_LaTeX_symbols = 1; # Starts out on. 154: 155: sub enable_LaTeX_substitutions { 156: $Apache::lonxml::substitute_LaTeX_symbols = 1; 157: } 158: sub disable_LaTeX_substitutions { 159: $Apache::lonxml::substitute_LaTeX_symbols = 0; 160: } 161: 162: sub xmlend { 163: my ($target,$parser)=@_; 164: my $mode='xml'; 165: my $status='OPEN'; 166: if ($Apache::lonhomework::parsing_a_problem || 167: $Apache::lonhomework::parsing_a_task ) { 168: $mode='problem'; 169: $status=$Apache::inputtags::status[-1]; 170: } 171: my $discussion; 172: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, 173: ['LONCAPA_INTERNAL_no_discussion']); 174: if (! exists($env{'form.LONCAPA_INTERNAL_no_discussion'}) || 175: $env{'form.LONCAPA_INTERNAL_no_discussion'} ne 'true') { 176: $discussion=&Apache::lonfeedback::list_discussion($mode,$status); 177: } 178: if ($target eq 'tex') { 179: $discussion.='<tex>\keephidden{ENDOFPROBLEM}\vskip 0.5mm\noindent\makebox[\textwidth/$number_of_columns][b]{\hrulefill}\end{document}</tex>'; 180: &Apache::lonxml::newparser($parser,\$discussion,''); 181: return ''; 182: } 183: 184: return $discussion; 185: } 186: 187: sub tokeninputfield { 188: my $defhost=$Apache::lonnet::perlvar{'lonHostID'}; 189: $defhost=~tr/a-z/A-Z/; 190: return (<<ENDINPUTFIELD) 191: <script type="text/javascript"> 192: function updatetoken() { 193: var comp=new Array; 194: var barcode=unescape(document.tokeninput.barcode.value); 195: comp=barcode.split('*'); 196: if (typeof(comp[0])!="undefined") { 197: document.tokeninput.codeone.value=comp[0]; 198: } 199: if (typeof(comp[1])!="undefined") { 200: document.tokeninput.codetwo.value=comp[1]; 201: } 202: if (typeof(comp[2])!="undefined") { 203: comp[2]=comp[2].toUpperCase(); 204: document.tokeninput.codethree.value=comp[2]; 205: } 206: document.tokeninput.barcode.value=''; 207: } 208: </script> 209: <form method="post" name="tokeninput"> 210: <table border="2" bgcolor="#FFFFBB"> 211: <tr><th>DocID Checkin</th></tr> 212: <tr><td> 213: <table> 214: <tr> 215: <td>Scan in Barcode</td> 216: <td><input type="text" size="22" name="barcode" 217: onChange="updatetoken()"/></td> 218: </tr> 219: <tr><td><i>or</i> Type in DocID</td> 220: <td> 221: <input type="text" size="5" name="codeone" /> 222: <b><font size="+2">*</font></b> 223: <input type="text" size="5" name="codetwo" /> 224: <b><font size="+2">*</font></b> 225: <input type="text" size="10" name="codethree" value="$defhost" 226: onChange="this.value=this.value.toUpperCase()" /> 227: </td></tr> 228: </table> 229: </td></tr> 230: <tr><td><input type="submit" value="Check in DocID" /></td></tr> 231: </table> 232: </form> 233: ENDINPUTFIELD 234: } 235: 236: sub maketoken { 237: my ($symb,$tuname,$tudom,$tcrsid)=@_; 238: unless ($symb) { 239: $symb=&Apache::lonnet::symbread(); 240: } 241: unless ($tuname) { 242: $tuname=$env{'user.name'}; 243: $tudom=$env{'user.domain'}; 244: $tcrsid=$env{'request.course.id'}; 245: } 246: 247: return &Apache::lonnet::checkout($symb,$tuname,$tudom,$tcrsid); 248: } 249: 250: sub printtokenheader { 251: my ($target,$token,$tsymb,$tcrsid,$tudom,$tuname)=@_; 252: unless ($token) { return ''; } 253: 254: my ($symb,$courseid,$domain,$name) = &Apache::lonnet::whichuser(); 255: unless ($tsymb) { 256: $tsymb=$symb; 257: } 258: unless ($tuname) { 259: $tuname=$name; 260: $tudom=$domain; 261: $tcrsid=$courseid; 262: } 263: 264: my $plainname=&Apache::loncommon::plainname($tuname,$tudom); 265: 266: if ($target eq 'web') { 267: my %idhash=&Apache::lonnet::idrget($tudom,($tuname)); 268: return 269: '<img align="right" src="/cgi-bin/barcode.png?encode='.$token.'" />'. 270: &mt('Checked out for').' '.$plainname. 271: '<br />'.&mt('User').': '.$tuname.' at '.$tudom. 272: '<br />'.&mt('ID').': '.$idhash{$tuname}. 273: '<br />'.&mt('CourseID').': '.$tcrsid. 274: '<br />'.&mt('Course').': '.$env{'course.'.$tcrsid.'.description'}. 275: '<br />'.&mt('DocID').': '.$token. 276: '<br />'.&mt('Time').': '.&Apache::lonlocal::locallocaltime().'<hr />'; 277: } else { 278: return $token; 279: } 280: } 281: 282: sub printalltags { 283: my $temp; 284: foreach $temp (sort keys %Apache::lonxml::alltags) { 285: &Apache::lonxml::debug("$temp -- ". 286: join(',',@{ $Apache::lonxml::alltags{$temp} })); 287: } 288: } 289: 290: sub xmlparse { 291: my ($request,$target,$content_file_string,$safeinit,%style_for_target) = @_; 292: 293: &setup_globals($request,$target); 294: &Apache::inputtags::initialize_inputtags(); 295: &Apache::bridgetask::initialize_bridgetask(); 296: &Apache::outputtags::initialize_outputtags(); 297: &Apache::edit::initialize_edit(); 298: &Apache::londefdef::initialize_londefdef(); 299: 300: # 301: # do we have a course style file? 302: # 303: 304: if ($env{'request.course.id'} && $env{'request.state'} ne 'construct') { 305: my $bodytext= 306: $env{'course.'.$env{'request.course.id'}.'.default_xml_style'}; 307: if ($bodytext) { 308: foreach my $file (split(',',$bodytext)) { 309: my $location=&Apache::lonnet::filelocation('',$file); 310: my $styletext=&Apache::lonnet::getfile($location); 311: if ($styletext ne '-1') { 312: %style_for_target = (%style_for_target, 313: &Apache::style::styleparser($target,$styletext)); 314: } 315: } 316: } 317: } elsif ($env{'construct.style'} && ($env{'request.state'} eq 'construct')) { 318: my $location=&Apache::lonnet::filelocation('',$env{'construct.style'}); 319: my $styletext=&Apache::lonnet::getfile($location); 320: if ($styletext ne '-1') { 321: %style_for_target = (%style_for_target, 322: &Apache::style::styleparser($target,$styletext)); 323: } 324: } 325: #&printalltags(); 326: my @pars = (); 327: my $pwd=$env{'request.filename'}; 328: $pwd =~ s:/[^/]*$::; 329: &newparser(\@pars,\$content_file_string,$pwd); 330: 331: my $safeeval = new Safe; 332: my $safehole = new Safe::Hole; 333: &init_safespace($target,$safeeval,$safehole,$safeinit); 334: #-------------------- Redefinition of the target in the case of compound target 335: 336: ($target, my @tenta) = split('&&',$target); 337: 338: my @stack = (); 339: my @parstack = (); 340: &initdepth(); 341: &init_alarm(); 342: my $finaloutput = &inner_xmlparse($target,\@stack,\@parstack,\@pars, 343: $safeeval,\%style_for_target,1); 344: 345: if (@stack) { 346: &warning("At end of file some tags were still left unclosed, ". 347: '<tt><'.join('></tt>, <tt><',reverse(@stack)). 348: '></tt>'); 349: } 350: if ($env{'request.uri'}) { 351: &writeallows($env{'request.uri'}); 352: } 353: &do_registered_ssi(); 354: if ($Apache::lonxml::counter_changed) { &store_counter() } 355: 356: &clean_safespace($safeeval); 357: 358: if ($env{'form.return_only_error_and_warning_counts'}) { 359: return "$errorcount:$warningcount"; 360: } 361: return $finaloutput; 362: } 363: 364: sub latex_special_symbols { 365: my ($string,$where)=@_; 366: # 367: # If e.g. in verbatim mode, then don't substitute. 368: # but return original string. 369: # 370: if (!($Apache::lonxml::substitute_LaTeX_symbols)) { 371: return $string; 372: } 373: if ($where eq 'header') { 374: $string =~ s/\\/\$\\backslash\$/g; # \ -> $\backslash$ per LaTex line by line pg 10. 375: $string =~ s/(\$|%|\{|\})/\\$1/g; 376: $string=&Apache::lonprintout::character_chart($string); 377: # any & or # leftover should be safe to just escape 378: $string=~s/([^\\])\&/$1\\\&/g; 379: $string=~s/([^\\])\#/$1\\\#/g; 380: $string =~ s/_/\\_/g; # _ -> \_ 381: $string =~ s/\^/\\\^{}/g; # ^ -> \^{} 382: } else { 383: $string=~s/\\/\\ensuremath{\\backslash}/g; 384: $string=~s/\\\%|\%/\\\%/g; 385: $string=~s/\\{|{/\\{/g; 386: $string=~s/\\}|}/\\}/g; 387: $string=~s/\\ensuremath\\{\\backslash\\}/\\ensuremath{\\backslash}/g; 388: $string=~s/\\\$|\$/\\\$/g; 389: $string=~s/\\\_|\_/\\\_/g; 390: $string=~s/([^\\]|^)(\~|\^)/$1\\$2\\strut /g; 391: $string=~s/(>|<)/\\ensuremath\{$1\}/g; #more or less 392: $string=&Apache::lonprintout::character_chart($string); 393: # any & or # leftover should be safe to just escape 394: $string=~s/\\\&|\&/\\\&/g; 395: $string=~s/\\\#|\#/\\\#/g; 396: $string=~s/\|/\$\\mid\$/g; 397: #single { or } How to escape? 398: } 399: return $string; 400: } 401: 402: sub inner_xmlparse { 403: my ($target,$stack,$parstack,$pars,$safeeval,$style_for_target,$start)=@_; 404: my $finaloutput = ''; 405: my $result; 406: my $token; 407: my $dontpop=0; 408: my $startredirection = $Apache::lonxml::redirection; 409: while ( $#$pars > -1 ) { 410: while ($token = $$pars['-1']->get_token) { 411: if (($token->[0] eq 'T') || ($token->[0] eq 'C') ) { 412: if ($metamode<1) { 413: my $text=$token->[1]; 414: if ($token->[0] eq 'C' && $target eq 'tex') { 415: $text = ''; 416: # $text = '%'.$text."\n"; 417: } 418: $result.=$text; 419: } 420: } elsif (($token->[0] eq 'D')) { 421: if ($metamode<1 && $target eq 'web') { 422: my $text=$token->[1]; 423: $result.=$text; 424: } 425: } elsif ($token->[0] eq 'PI') { 426: if ($metamode<1 && $target eq 'web') { 427: $result=$token->[2]; 428: } 429: } elsif ($token->[0] eq 'S') { 430: # add tag to stack 431: push (@$stack,$token->[1]); 432: # add parameters list to another stack 433: push (@$parstack,&parstring($token)); 434: &increasedepth($token); 435: if ($Apache::lonxml::usestyle && 436: exists($$style_for_target{$token->[1]})) { 437: $Apache::lonxml::usestyle=0; 438: my $string=$$style_for_target{$token->[1]}. 439: '<LONCAPA_INTERNAL_TURN_STYLE_ON />'; 440: &Apache::lonxml::newparser($pars,\$string); 441: $Apache::lonxml::style_values=$$parstack[-1]; 442: $Apache::lonxml::style_end_values=$$parstack[-1]; 443: } else { 444: $result = &callsub("start_$token->[1]", $target, $token, $stack, 445: $parstack, $pars, $safeeval, $style_for_target); 446: } 447: } elsif ($token->[0] eq 'E') { 448: if ($Apache::lonxml::usestyle && 449: exists($$style_for_target{'/'."$token->[1]"})) { 450: $Apache::lonxml::usestyle=0; 451: my $string=$$style_for_target{'/'.$token->[1]}. 452: '<LONCAPA_INTERNAL_TURN_STYLE_ON end="'.$token->[1].'" />'; 453: &Apache::lonxml::newparser($pars,\$string); 454: $Apache::lonxml::style_values=$Apache::lonxml::style_end_values; 455: $Apache::lonxml::style_end_values=''; 456: $dontpop=1; 457: } else { 458: #clear out any tags that didn't end 459: while ($token->[1] ne $$stack['-1'] && ($#$stack > -1)) { 460: my $lasttag=$$stack[-1]; 461: if ($token->[1] =~ /^\Q$lasttag\E$/i) { 462: &Apache::lonxml::warning('Using tag </'.$token->[1].'> on line '.$token->[3].' as end tag to <'.$$stack[-1].'>'); 463: last; 464: } else { 465: &Apache::lonxml::warning('Found tag </'.$token->[1].'> on line '.$token->[3].' when looking for </'.$$stack[-1].'> in file'); 466: &end_tag($stack,$parstack,$token); 467: } 468: } 469: $result = &callsub("end_$token->[1]", $target, $token, $stack, 470: $parstack, $pars,$safeeval, $style_for_target); 471: } 472: } else { 473: &Apache::lonxml::error("Unknown token event :$token->[0]:$token->[1]:"); 474: } 475: #evaluate variable refs in result 476: if ($Apache::lonxml::post_evaluate &&$result ne "") { 477: my $extras; 478: if (!$Apache::lonxml::usestyle) { 479: $extras=$Apache::lonxml::style_values; 480: } 481: if ( $#$parstack > -1 ) { 482: $result=&Apache::run::evaluate($result,$safeeval,$extras.$$parstack[-1]); 483: } else { 484: $result= &Apache::run::evaluate($result,$safeeval,$extras); 485: } 486: } 487: $Apache::lonxml::post_evaluate=1; 488: 489: if (($token->[0] eq 'T') || ($token->[0] eq 'C') || ($token->[0] eq 'D') ) { 490: #Style file definitions should be correct 491: if ($target eq 'tex' && ($Apache::lonxml::usestyle)) { 492: $result=&latex_special_symbols($result); 493: } 494: } 495: 496: if ($Apache::lonxml::redirection) { 497: $Apache::lonxml::outputstack['-1'] .= $result; 498: } else { 499: $finaloutput.=$result; 500: } 501: $result = ''; 502: 503: if ($token->[0] eq 'E' && !$dontpop) { 504: &end_tag($stack,$parstack,$token); 505: } 506: $dontpop=0; 507: } 508: if ($#$pars > -1) { 509: pop @$pars; 510: pop @Apache::lonxml::pwd; 511: } 512: } 513: 514: # if ($target eq 'meta') { 515: # $finaloutput.=&endredirection; 516: # } 517: 518: if ( $start && $target eq 'grade') { &endredirection(); } 519: if ( $Apache::lonxml::redirection > $startredirection) { 520: while ($Apache::lonxml::redirection > $startredirection) { 521: $finaloutput .= &endredirection(); 522: } 523: } 524: if (($ENV{'QUERY_STRING'}) && ($target eq 'web')) { 525: $finaloutput=&afterburn($finaloutput); 526: } 527: return $finaloutput; 528: } 529: 530: ## 531: ## Looks to see if there is a subroutine defined for this tag. If so, call it, 532: ## otherwise do not call it as we do not know what it is. 533: ## 534: sub callsub { 535: my ($sub,$target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; 536: my $currentstring=''; 537: my $nodefault; 538: { 539: my $sub1; 540: no strict 'refs'; 541: my $tag=$token->[1]; 542: # get utterly rid of extended html tags 543: if ($tag=~/^x\-/i) { return ''; } 544: my $space=$Apache::lonxml::alltags{$tag}[-1]; 545: if (!$space) { 546: $tag=~tr/A-Z/a-z/; 547: $sub=~tr/A-Z/a-z/; 548: $space=$Apache::lonxml::alltags{$tag}[-1] 549: } 550: 551: my $deleted=0; 552: $Apache::lonxml::curdepth=join('_',@Apache::lonxml::depthcounter); 553: if (($token->[0] eq 'S') && ($target eq 'modified')) { 554: $deleted=&Apache::edit::handle_delete($space,$target,$token,$tagstack, 555: $parstack,$parser,$safeeval, 556: $style); 557: } 558: if (!$deleted) { 559: if ($space) { 560: #&Apache::lonxml::debug("Calling sub $sub in $space $metamode"); 561: $sub1="$space\:\:$sub"; 562: ($currentstring,$nodefault) = &$sub1($target,$token,$tagstack, 563: $parstack,$parser,$safeeval, 564: $style); 565: } else { 566: if ($target eq 'tex') { 567: # throw away tag name 568: return ''; 569: } 570: #&Apache::lonxml::debug("NOT Calling sub $sub in $space $metamode"); 571: if ($metamode <1) { 572: if (defined($token->[4]) && ($metamode < 1)) { 573: $currentstring = $token->[4]; 574: } else { 575: $currentstring = $token->[2]; 576: } 577: } 578: } 579: # &Apache::lonxml::debug("nodefalt:$nodefault:"); 580: if ($currentstring eq '' && $nodefault eq '') { 581: if ($target eq 'edit') { 582: #&Apache::lonxml::debug("doing default edit for $token->[1]"); 583: if ($token->[0] eq 'S') { 584: $currentstring = &Apache::edit::tag_start($target,$token); 585: } elsif ($token->[0] eq 'E') { 586: $currentstring = &Apache::edit::tag_end($target,$token); 587: } 588: } elsif ($target eq 'modified') { 589: if ($token->[0] eq 'S') { 590: $currentstring = $token->[4]; 591: $currentstring.=&Apache::edit::handle_insert(); 592: } elsif ($token->[0] eq 'E') { 593: $currentstring = $token->[2]; 594: $currentstring.=&Apache::edit::handle_insertafter($token->[1]); 595: } else { 596: $currentstring = $token->[2]; 597: } 598: } 599: } 600: } 601: use strict 'refs'; 602: } 603: return $currentstring; 604: } 605: 606: sub setup_globals { 607: my ($request,$target)=@_; 608: $Apache::lonxml::request=$request; 609: $errorcount=0; 610: $warningcount=0; 611: $Apache::lonxml::default_homework_loaded=0; 612: $Apache::lonxml::usestyle=1; 613: &init_counter(); 614: @Apache::lonxml::pwd=(); 615: @Apache::lonxml::extlinks=(); 616: @Apache::lonxml::ssi_info=(); 617: $Apache::lonxml::post_evaluate=1; 618: $Apache::lonxml::warnings_error_header=''; 619: $Apache::lonxml::substitute_LaTeX_symbols = 1; 620: if ($target eq 'meta') { 621: $Apache::lonxml::redirection = 0; 622: $Apache::lonxml::metamode = 1; 623: $Apache::lonxml::evaluate = 1; 624: $Apache::lonxml::import = 0; 625: } elsif ($target eq 'answer') { 626: $Apache::lonxml::redirection = 0; 627: $Apache::lonxml::metamode = 1; 628: $Apache::lonxml::evaluate = 1; 629: $Apache::lonxml::import = 1; 630: } elsif ($target eq 'grade') { 631: &startredirection(); #ended in inner_xmlparse on exit 632: $Apache::lonxml::metamode = 0; 633: $Apache::lonxml::evaluate = 1; 634: $Apache::lonxml::import = 1; 635: } elsif ($target eq 'modified') { 636: $Apache::lonxml::redirection = 0; 637: $Apache::lonxml::metamode = 0; 638: $Apache::lonxml::evaluate = 0; 639: $Apache::lonxml::import = 0; 640: } elsif ($target eq 'edit') { 641: $Apache::lonxml::redirection = 0; 642: $Apache::lonxml::metamode = 0; 643: $Apache::lonxml::evaluate = 0; 644: $Apache::lonxml::import = 0; 645: } elsif ($target eq 'analyze') { 646: $Apache::lonxml::redirection = 0; 647: $Apache::lonxml::metamode = 0; 648: $Apache::lonxml::evaluate = 1; 649: $Apache::lonxml::import = 1; 650: } else { 651: $Apache::lonxml::redirection = 0; 652: $Apache::lonxml::metamode = 0; 653: $Apache::lonxml::evaluate = 1; 654: $Apache::lonxml::import = 1; 655: } 656: } 657: 658: sub init_safespace { 659: my ($target,$safeeval,$safehole,$safeinit) = @_; 660: $safeeval->deny_only(':dangerous'); 661: $safeeval->reval('use Math::Complex;'); 662: $safeeval->permit_only(":default"); 663: $safeeval->permit("entereval"); 664: $safeeval->permit(":base_math"); 665: $safeeval->permit("sort"); 666: $safeeval->permit("time"); 667: $safeeval->deny("rand"); 668: $safeeval->deny("srand"); 669: $safeeval->deny(":base_io"); 670: $safehole->wrap(\&Apache::scripttag::xmlparse,$safeeval,'&xmlparse'); 671: $safehole->wrap(\&Apache::outputtags::multipart,$safeeval,'&multipart'); 672: $safehole->wrap(\&Apache::lonnet::EXT,$safeeval,'&EXT'); 673: $safehole->wrap(\&Apache::chemresponse::chem_standard_order,$safeeval, 674: '&chem_standard_order'); 675: $safehole->wrap(\&Apache::response::check_status,$safeeval,'&check_status'); 676: 677: $safehole->wrap(\&Math::Cephes::asin,$safeeval,'&asin'); 678: $safehole->wrap(\&Math::Cephes::acos,$safeeval,'&acos'); 679: $safehole->wrap(\&Math::Cephes::atan,$safeeval,'&atan'); 680: $safehole->wrap(\&Math::Cephes::sinh,$safeeval,'&sinh'); 681: $safehole->wrap(\&Math::Cephes::cosh,$safeeval,'&cosh'); 682: $safehole->wrap(\&Math::Cephes::tanh,$safeeval,'&tanh'); 683: $safehole->wrap(\&Math::Cephes::asinh,$safeeval,'&asinh'); 684: $safehole->wrap(\&Math::Cephes::acosh,$safeeval,'&acosh'); 685: $safehole->wrap(\&Math::Cephes::atanh,$safeeval,'&atanh'); 686: $safehole->wrap(\&Math::Cephes::erf,$safeeval,'&erf'); 687: $safehole->wrap(\&Math::Cephes::erfc,$safeeval,'&erfc'); 688: $safehole->wrap(\&Math::Cephes::j0,$safeeval,'&j0'); 689: $safehole->wrap(\&Math::Cephes::j1,$safeeval,'&j1'); 690: $safehole->wrap(\&Math::Cephes::jn,$safeeval,'&jn'); 691: $safehole->wrap(\&Math::Cephes::jv,$safeeval,'&jv'); 692: $safehole->wrap(\&Math::Cephes::y0,$safeeval,'&y0'); 693: $safehole->wrap(\&Math::Cephes::y1,$safeeval,'&y1'); 694: $safehole->wrap(\&Math::Cephes::yn,$safeeval,'&yn'); 695: $safehole->wrap(\&Math::Cephes::yv,$safeeval,'&yv'); 696: 697: $safehole->wrap(\&Math::Cephes::bdtr ,$safeeval,'&bdtr' ); 698: $safehole->wrap(\&Math::Cephes::bdtrc ,$safeeval,'&bdtrc' ); 699: $safehole->wrap(\&Math::Cephes::bdtri ,$safeeval,'&bdtri' ); 700: $safehole->wrap(\&Math::Cephes::btdtr ,$safeeval,'&btdtr' ); 701: $safehole->wrap(\&Math::Cephes::chdtr ,$safeeval,'&chdtr' ); 702: $safehole->wrap(\&Math::Cephes::chdtrc,$safeeval,'&chdtrc'); 703: $safehole->wrap(\&Math::Cephes::chdtri,$safeeval,'&chdtri'); 704: $safehole->wrap(\&Math::Cephes::fdtr ,$safeeval,'&fdtr' ); 705: $safehole->wrap(\&Math::Cephes::fdtrc ,$safeeval,'&fdtrc' ); 706: $safehole->wrap(\&Math::Cephes::fdtri ,$safeeval,'&fdtri' ); 707: $safehole->wrap(\&Math::Cephes::gdtr ,$safeeval,'&gdtr' ); 708: $safehole->wrap(\&Math::Cephes::gdtrc ,$safeeval,'&gdtrc' ); 709: $safehole->wrap(\&Math::Cephes::nbdtr ,$safeeval,'&nbdtr' ); 710: $safehole->wrap(\&Math::Cephes::nbdtrc,$safeeval,'&nbdtrc'); 711: $safehole->wrap(\&Math::Cephes::nbdtri,$safeeval,'&nbdtri'); 712: $safehole->wrap(\&Math::Cephes::ndtr ,$safeeval,'&ndtr' ); 713: $safehole->wrap(\&Math::Cephes::ndtri ,$safeeval,'&ndtri' ); 714: $safehole->wrap(\&Math::Cephes::pdtr ,$safeeval,'&pdtr' ); 715: $safehole->wrap(\&Math::Cephes::pdtrc ,$safeeval,'&pdtrc' ); 716: $safehole->wrap(\&Math::Cephes::pdtri ,$safeeval,'&pdtri' ); 717: $safehole->wrap(\&Math::Cephes::stdtr ,$safeeval,'&stdtr' ); 718: $safehole->wrap(\&Math::Cephes::stdtri,$safeeval,'&stdtri'); 719: 720: $safehole->wrap(\&Math::Cephes::Matrix::mat,$safeeval,'&mat'); 721: $safehole->wrap(\&Math::Cephes::Matrix::new,$safeeval, 722: '&Math::Cephes::Matrix::new'); 723: $safehole->wrap(\&Math::Cephes::Matrix::coef,$safeeval, 724: '&Math::Cephes::Matrix::coef'); 725: $safehole->wrap(\&Math::Cephes::Matrix::clr,$safeeval, 726: '&Math::Cephes::Matrix::clr'); 727: $safehole->wrap(\&Math::Cephes::Matrix::add,$safeeval, 728: '&Math::Cephes::Matrix::add'); 729: $safehole->wrap(\&Math::Cephes::Matrix::sub,$safeeval, 730: '&Math::Cephes::Matrix::sub'); 731: $safehole->wrap(\&Math::Cephes::Matrix::mul,$safeeval, 732: '&Math::Cephes::Matrix::mul'); 733: $safehole->wrap(\&Math::Cephes::Matrix::div,$safeeval, 734: '&Math::Cephes::Matrix::div'); 735: $safehole->wrap(\&Math::Cephes::Matrix::inv,$safeeval, 736: '&Math::Cephes::Matrix::inv'); 737: $safehole->wrap(\&Math::Cephes::Matrix::transp,$safeeval, 738: '&Math::Cephes::Matrix::transp'); 739: $safehole->wrap(\&Math::Cephes::Matrix::simq,$safeeval, 740: '&Math::Cephes::Matrix::simq'); 741: $safehole->wrap(\&Math::Cephes::Matrix::mat_to_vec,$safeeval, 742: '&Math::Cephes::Matrix::mat_to_vec'); 743: $safehole->wrap(\&Math::Cephes::Matrix::vec_to_mat,$safeeval, 744: '&Math::Cephes::Matrix::vec_to_mat'); 745: $safehole->wrap(\&Math::Cephes::Matrix::check,$safeeval, 746: '&Math::Cephes::Matrix::check'); 747: $safehole->wrap(\&Math::Cephes::Matrix::check,$safeeval, 748: '&Math::Cephes::Matrix::check'); 749: 750: # $safehole->wrap(\&Math::Cephes::new_fract,$safeeval,'&new_fract'); 751: # $safehole->wrap(\&Math::Cephes::radd,$safeeval,'&radd'); 752: # $safehole->wrap(\&Math::Cephes::rsub,$safeeval,'&rsub'); 753: # $safehole->wrap(\&Math::Cephes::rmul,$safeeval,'&rmul'); 754: # $safehole->wrap(\&Math::Cephes::rdiv,$safeeval,'&rdiv'); 755: # $safehole->wrap(\&Math::Cephes::euclid,$safeeval,'&euclid'); 756: 757: $safehole->wrap(\&Math::Random::random_beta,$safeeval,'&math_random_beta'); 758: $safehole->wrap(\&Math::Random::random_chi_square,$safeeval,'&math_random_chi_square'); 759: $safehole->wrap(\&Math::Random::random_exponential,$safeeval,'&math_random_exponential'); 760: $safehole->wrap(\&Math::Random::random_f,$safeeval,'&math_random_f'); 761: $safehole->wrap(\&Math::Random::random_gamma,$safeeval,'&math_random_gamma'); 762: $safehole->wrap(\&Math::Random::random_multivariate_normal,$safeeval,'&math_random_multivariate_normal'); 763: $safehole->wrap(\&Math::Random::random_multinomial,$safeeval,'&math_random_multinomial'); 764: $safehole->wrap(\&Math::Random::random_noncentral_chi_square,$safeeval,'&math_random_noncentral_chi_square'); 765: $safehole->wrap(\&Math::Random::random_noncentral_f,$safeeval,'&math_random_noncentral_f'); 766: $safehole->wrap(\&Math::Random::random_normal,$safeeval,'&math_random_normal'); 767: $safehole->wrap(\&Math::Random::random_permutation,$safeeval,'&math_random_permutation'); 768: $safehole->wrap(\&Math::Random::random_permuted_index,$safeeval,'&math_random_permuted_index'); 769: $safehole->wrap(\&Math::Random::random_uniform,$safeeval,'&math_random_uniform'); 770: $safehole->wrap(\&Math::Random::random_poisson,$safeeval,'&math_random_poisson'); 771: $safehole->wrap(\&Math::Random::random_uniform_integer,$safeeval,'&math_random_uniform_integer'); 772: $safehole->wrap(\&Math::Random::random_negative_binomial,$safeeval,'&math_random_negative_binomial'); 773: $safehole->wrap(\&Math::Random::random_binomial,$safeeval,'&math_random_binomial'); 774: $safehole->wrap(\&Math::Random::random_seed_from_phrase,$safeeval,'&random_seed_from_phrase'); 775: $safehole->wrap(\&Math::Random::random_set_seed_from_phrase,$safeeval,'&random_set_seed_from_phrase'); 776: $safehole->wrap(\&Math::Random::random_get_seed,$safeeval,'&random_get_seed'); 777: $safehole->wrap(\&Math::Random::random_set_seed,$safeeval,'&random_set_seed'); 778: $safehole->wrap(\&Apache::lonxml::error,$safeeval,'&LONCAPA_INTERNAL_ERROR'); 779: $safehole->wrap(\&Apache::lonxml::debug,$safeeval,'&LONCAPA_INTERNAL_DEBUG'); 780: $safehole->wrap(\&Apache::lonnet::logthis,$safeeval,'&LONCAPA_INTERNAL_LOGTHIS'); 781: $safehole->wrap(\&Apache::inputtags::finalizeawards,$safeeval,'&LONCAPA_INTERNAL_FINALIZEAWARDS'); 782: $safehole->wrap(\&Apache::caparesponse::get_sigrange,$safeeval,'&LONCAPA_INTERNAL_get_sigrange'); 783: use Data::Dumper; 784: $safehole->wrap(\&Data::Dumper::Dumper,$safeeval,'&LONCAPA_INTERNAL_Dumper'); 785: #need to inspect this class of ops 786: # $safeeval->deny(":base_orig"); 787: $safeeval->permit("require"); 788: $safeinit .= ';$external::target="'.$target.'";'; 789: &Apache::run::run($safeinit,$safeeval); 790: &initialize_rndseed($safeeval); 791: } 792: 793: sub clean_safespace { 794: my ($safeeval) = @_; 795: delete_package_recurse($safeeval->{Root}); 796: } 797: 798: sub delete_package_recurse { 799: my ($package) = @_; 800: my @subp; 801: { 802: no strict 'refs'; 803: while (my ($key,$val) = each(%{*{"$package\::"}})) { 804: if (!defined($val)) { next; } 805: local (*ENTRY) = $val; 806: if (defined *ENTRY{HASH} && $key =~ /::$/ && 807: $key ne "main::" && $key ne "<none>::") 808: { 809: my ($p) = $package ne "main" ? "$package\::" : ""; 810: ($p .= $key) =~ s/::$//; 811: push(@subp,$p); 812: } 813: } 814: } 815: foreach my $p (@subp) { 816: delete_package_recurse($p); 817: } 818: Symbol::delete_package($package); 819: } 820: 821: sub initialize_rndseed { 822: my ($safeeval)=@_; 823: my $rndseed; 824: my ($symb,$courseid,$domain,$name) = &Apache::lonnet::whichuser(); 825: $rndseed=&Apache::lonnet::rndseed($symb,$courseid,$domain,$name); 826: my $safeinit = '$external::randomseed="'.$rndseed.'";'; 827: &Apache::lonxml::debug("Setting rndseed to $rndseed"); 828: &Apache::run::run($safeinit,$safeeval); 829: } 830: 831: sub default_homework_load { 832: my ($safeeval)=@_; 833: &Apache::lonxml::debug('Loading default_homework'); 834: my $default=&Apache::lonnet::getfile('/home/httpd/html/res/adm/includes/default_homework.lcpm'); 835: if ($default eq -1) { 836: &Apache::lonxml::error("<b>Unable to find <i>default_homework.lcpm</i></b>"); 837: } else { 838: &Apache::run::run($default,$safeeval); 839: $Apache::lonxml::default_homework_loaded=1; 840: } 841: } 842: 843: { 844: my $alarm_depth; 845: sub init_alarm { 846: alarm(0); 847: $alarm_depth=0; 848: } 849: 850: sub start_alarm { 851: if ($alarm_depth<1) { 852: my $old=alarm($Apache::lonnet::perlvar{'lonScriptTimeout'}); 853: if ($old) { 854: &Apache::lonxml::error("Cancelled an alarm of $old, this shouldn't occur."); 855: } 856: } 857: $alarm_depth++; 858: } 859: 860: sub end_alarm { 861: $alarm_depth--; 862: if ($alarm_depth<1) { alarm(0); } 863: } 864: } 865: my $metamode_was; 866: sub startredirection { 867: if (!$Apache::lonxml::redirection) { 868: $metamode_was=$Apache::lonxml::metamode; 869: } 870: $Apache::lonxml::metamode=0; 871: $Apache::lonxml::redirection++; 872: push (@Apache::lonxml::outputstack, ''); 873: } 874: 875: sub endredirection { 876: if (!$Apache::lonxml::redirection) { 877: &Apache::lonxml::error("Endredirection was called before a startredirection, perhaps you have unbalanced tags. Some debugging information:".join ":",caller); 878: return ''; 879: } 880: $Apache::lonxml::redirection--; 881: if (!$Apache::lonxml::redirection) { 882: $Apache::lonxml::metamode=$metamode_was; 883: } 884: pop @Apache::lonxml::outputstack; 885: } 886: 887: sub end_tag { 888: my ($tagstack,$parstack,$token)=@_; 889: pop(@$tagstack); 890: pop(@$parstack); 891: &decreasedepth($token); 892: } 893: 894: sub initdepth { 895: @Apache::lonxml::depthcounter=(); 896: $Apache::lonxml::depth=-1; 897: $Apache::lonxml::olddepth=-1; 898: } 899: 900: my @timers; 901: my $lasttime; 902: sub increasedepth { 903: my ($token) = @_; 904: $Apache::lonxml::depth++; 905: $Apache::lonxml::depthcounter[$Apache::lonxml::depth]++; 906: if ($Apache::lonxml::depthcounter[$Apache::lonxml::depth]==1) { 907: $Apache::lonxml::olddepth=$Apache::lonxml::depth; 908: } 909: my $time; 910: if ($Apache::lonxml::debug eq "1") { 911: push(@timers,[&gettimeofday()]); 912: $time=&tv_interval($lasttime); 913: $lasttime=[&gettimeofday()]; 914: } 915: my $spacing=' 'x($Apache::lonxml::depth-1); 916: my $curdepth=join('_',@Apache::lonxml::depthcounter); 917: &Apache::lonxml::debug("s$spacing$Apache::lonxml::depth : $Apache::lonxml::olddepth : $curdepth : $token->[1] : $time : \n"); 918: #print "<br />s $Apache::lonxml::depth : $Apache::lonxml::olddepth : $curdepth : $token->[1]\n"; 919: } 920: 921: sub decreasedepth { 922: my ($token) = @_; 923: $Apache::lonxml::depth--; 924: if ($Apache::lonxml::depth<$Apache::lonxml::olddepth-1) { 925: $#Apache::lonxml::depthcounter--; 926: $Apache::lonxml::olddepth=$Apache::lonxml::depth+1; 927: } 928: if ( $Apache::lonxml::depth < -1) { 929: &Apache::lonxml::warning(&mt("Missing tags, unable to properly run file.")); 930: $Apache::lonxml::depth='-1'; 931: } 932: my ($timer,$time); 933: if ($Apache::lonxml::debug eq "1") { 934: $timer=pop(@timers); 935: $time=&tv_interval($lasttime); 936: $lasttime=[&gettimeofday()]; 937: } 938: my $spacing=' 'x$Apache::lonxml::depth; 939: my $curdepth=join('_',@Apache::lonxml::depthcounter); 940: &Apache::lonxml::debug("e$spacing$Apache::lonxml::depth : $Apache::lonxml::olddepth : $curdepth : $token->[1] : $time : ".&tv_interval($timer)."\n"); 941: #print "<br />e $Apache::lonxml::depth : $Apache::lonxml::olddepth : $token->[1] : $curdepth\n"; 942: } 943: 944: sub get_id { 945: my ($parstack,$safeeval)=@_; 946: my $id= &Apache::lonxml::get_param('id',$parstack,$safeeval); 947: if ($env{'request.state'} eq 'construct' && $id =~ /(\.|_)/) { 948: &error(&mt("IDs are not allowed to contain "<tt>_</tt>" or "<tt>.</tt>"")); 949: } 950: if ($id =~ /^\s*$/) { $id = $Apache::lonxml::curdepth; } 951: return $id; 952: } 953: 954: sub get_all_text_unbalanced { 955: #there is a copy of this in lonpublisher.pm 956: my($tag,$pars)= @_; 957: my $token; 958: my $result=''; 959: $tag='<'.$tag.'>'; 960: while ($token = $$pars[-1]->get_token) { 961: if (($token->[0] eq 'T')||($token->[0] eq 'C')||($token->[0] eq 'D')) { 962: if ($token->[0] eq 'T' && $token->[2]) { 963: $result.='<![CDATA['.$token->[1].']]>'; 964: } else { 965: $result.=$token->[1]; 966: } 967: } elsif ($token->[0] eq 'PI') { 968: $result.=$token->[2]; 969: } elsif ($token->[0] eq 'S') { 970: $result.=$token->[4]; 971: } elsif ($token->[0] eq 'E') { 972: $result.=$token->[2]; 973: } 974: if ($result =~ /\Q$tag\E/is) { 975: ($result,my $redo)=$result =~ /(.*)\Q$tag\E(.*)/is; 976: #&Apache::lonxml::debug('Got a winner with leftovers ::'.$2); 977: #&Apache::lonxml::debug('Result is :'.$1); 978: $redo=$tag.$redo; 979: &Apache::lonxml::newparser($pars,\$redo); 980: last; 981: } 982: } 983: return $result 984: } 985: 986: sub increment_counter { 987: my ($increment) = @_; 988: if (defined($increment) && $increment gt 0) { 989: $Apache::lonxml::counter+=$increment; 990: } else { 991: $Apache::lonxml::counter++; 992: } 993: $Apache::lonxml::counter_changed=1; 994: } 995: 996: sub init_counter { 997: if ($env{'request.state'} eq 'construct') { 998: $Apache::lonxml::counter=1; 999: $Apache::lonxml::counter_changed=1; 1000: } elsif (defined($env{'form.counter'})) { 1001: $Apache::lonxml::counter=$env{'form.counter'}; 1002: $Apache::lonxml::counter_changed=0; 1003: } else { 1004: $Apache::lonxml::counter=1; 1005: $Apache::lonxml::counter_changed=1; 1006: } 1007: } 1008: 1009: sub store_counter { 1010: &Apache::lonnet::appenv(('form.counter' => $Apache::lonxml::counter)); 1011: $Apache::lonxml::counter_changed=0; 1012: return ''; 1013: } 1014: 1015: { 1016: my $state; 1017: sub clear_problem_counter { 1018: undef($state); 1019: &Apache::lonnet::delenv('form.counter'); 1020: &Apache::lonxml::init_counter(); 1021: &Apache::lonxml::store_counter(); 1022: } 1023: 1024: sub remember_problem_counter { 1025: &Apache::lonnet::transfer_profile_to_env(undef,undef,1); 1026: $state = $env{'form.counter'}; 1027: } 1028: 1029: sub restore_problem_counter { 1030: if (defined($state)) { 1031: &Apache::lonnet::appenv(('form.counter' => $state)); 1032: } 1033: } 1034: sub get_problem_counter { 1035: if ($Apache::lonxml::counter_changed) { &store_counter() } 1036: &Apache::lonnet::transfer_profile_to_env(undef,undef,1); 1037: return $env{'form.counter'}; 1038: } 1039: } 1040: 1041: sub get_all_text { 1042: my($tag,$pars,$style)= @_; 1043: my $gotfullstack=1; 1044: if (ref($pars) ne 'ARRAY') { 1045: $gotfullstack=0; 1046: $pars=[$pars]; 1047: } 1048: if (ref($style) ne 'HASH') { 1049: $style={}; 1050: } 1051: my $depth=0; 1052: my $token; 1053: my $result=''; 1054: if ( $tag =~ m:^/: ) { 1055: my $tag=substr($tag,1); 1056: #&Apache::lonxml::debug("have:$tag:"); 1057: my $top_empty=0; 1058: while (($depth >=0) && ($#$pars > -1) && (!$top_empty)) { 1059: while (($depth >=0) && ($token = $$pars[-1]->get_token)) { 1060: #&Apache::lonxml::debug("e token:$token->[0]:$depth:$token->[1]:".$#$pars.":".$#Apache::lonxml::pwd); 1061: if (($token->[0] eq 'T')||($token->[0] eq 'C')||($token->[0] eq 'D')) { 1062: if ($token->[2]) { 1063: $result.='<![CDATA['.$token->[1].']]>'; 1064: } else { 1065: $result.=$token->[1]; 1066: } 1067: } elsif ($token->[0] eq 'PI') { 1068: $result.=$token->[2]; 1069: } elsif ($token->[0] eq 'S') { 1070: if ($token->[1] =~ /^\Q$tag\E$/i) { $depth++; } 1071: if ($token->[1] =~ /^LONCAPA_INTERNAL_TURN_STYLE_ON$/) { $Apache::lonxml::usestyle=1; } 1072: if ($token->[1] =~ /^LONCAPA_INTERNAL_TURN_STYLE_OFF$/) { $Apache::lonxml::usestyle=0; } 1073: $result.=$token->[4]; 1074: } elsif ($token->[0] eq 'E') { 1075: if ( $token->[1] =~ /^\Q$tag\E$/i) { $depth--; } 1076: #skip sending back the last end tag 1077: if ($depth == 0 && exists($$style{'/'.$token->[1]}) && $Apache::lonxml::usestyle) { 1078: my $string= 1079: '<LONCAPA_INTERNAL_TURN_STYLE_OFF end="yes" />'. 1080: $$style{'/'.$token->[1]}. 1081: $token->[2]. 1082: '<LONCAPA_INTERNAL_TURN_STYLE_ON />'; 1083: &Apache::lonxml::newparser($pars,\$string); 1084: #&Apache::lonxml::debug("reParsing $string"); 1085: next; 1086: } 1087: if ($depth > -1) { 1088: $result.=$token->[2]; 1089: } else { 1090: $$pars[-1]->unget_token($token); 1091: } 1092: } 1093: } 1094: if (($depth >=0) && ($#$pars == 0) ) { $top_empty=1; } 1095: if (($depth >=0) && ($#$pars > 0) ) { 1096: pop(@$pars); 1097: pop(@Apache::lonxml::pwd); 1098: } 1099: } 1100: if ($top_empty && $depth >= 0) { 1101: #never found the end tag ran out of text, throw error send back blank 1102: &error('Never found end tag for <'.$tag. 1103: '> current string <pre>'. 1104: &HTML::Entities::encode($result,'<>&"'). 1105: '</pre>'); 1106: if ($gotfullstack) { 1107: my $newstring='</'.$tag.'>'.$result; 1108: &Apache::lonxml::newparser($pars,\$newstring); 1109: } 1110: $result=''; 1111: } 1112: } else { 1113: while ($#$pars > -1) { 1114: while ($token = $$pars[-1]->get_token) { 1115: #&Apache::lonxml::debug("s token:$token->[0]:$depth:$token->[1]"); 1116: if (($token->[0] eq 'T')||($token->[0] eq 'C')|| 1117: ($token->[0] eq 'D')) { 1118: if ($token->[2]) { 1119: $result.='<![CDATA['.$token->[1].']]>'; 1120: } else { 1121: $result.=$token->[1]; 1122: } 1123: } elsif ($token->[0] eq 'PI') { 1124: $result.=$token->[2]; 1125: } elsif ($token->[0] eq 'S') { 1126: if ( $token->[1] =~ /^\Q$tag\E$/i) { 1127: $$pars[-1]->unget_token($token); last; 1128: } else { 1129: $result.=$token->[4]; 1130: } 1131: if ($token->[1] =~ /^LONCAPA_INTERNAL_TURN_STYLE_ON$/) { $Apache::lonxml::usestyle=1; } 1132: if ($token->[1] =~ /^LONCAPA_INTERNAL_TURN_STYLE_OFF$/) { $Apache::lonxml::usestyle=0; } 1133: } elsif ($token->[0] eq 'E') { 1134: $result.=$token->[2]; 1135: } 1136: } 1137: if (($#$pars > 0) ) { 1138: pop(@$pars); 1139: pop(@Apache::lonxml::pwd); 1140: } else { last; } 1141: } 1142: } 1143: #&Apache::lonxml::debug("Exit:$result:"); 1144: return $result 1145: } 1146: 1147: sub newparser { 1148: my ($parser,$contentref,$dir) = @_; 1149: push (@$parser,HTML::LCParser->new($contentref)); 1150: $$parser[-1]->xml_mode(1); 1151: $$parser[-1]->marked_sections(1); 1152: if ( $dir eq '' ) { 1153: push (@Apache::lonxml::pwd, $Apache::lonxml::pwd[$#Apache::lonxml::pwd]); 1154: } else { 1155: push (@Apache::lonxml::pwd, $dir); 1156: } 1157: } 1158: 1159: sub parstring { 1160: my ($token) = @_; 1161: my (@vars,@values); 1162: foreach my $attr (@{$token->[3]}) { 1163: if ($attr!~/\W/) { 1164: my $val=$token->[2]->{$attr}; 1165: $val =~ s/([\%\@\\\"\'])/\\$1/g; 1166: $val =~ s/(\$[^\{a-zA-Z_])/\\$1/g; 1167: $val =~ s/(\$)$/\\$1/; 1168: #if ($val =~ m/^[\%\@]/) { $val="\\".$val; } 1169: push(@vars,"\$$attr"); 1170: push(@values,"\"$val\""); 1171: } 1172: } 1173: my $var_init = 1174: (@vars) ? 'my ('.join(',',@vars).') = ('.join(',',@values).');' 1175: : ''; 1176: return $var_init; 1177: } 1178: 1179: sub extlink { 1180: my ($res,$exact)=@_; 1181: if (!$exact) { 1182: $res=&Apache::lonnet::hreflocation($Apache::lonxml::pwd[-1],$res); 1183: } 1184: push(@Apache::lonxml::extlinks,$res) 1185: } 1186: 1187: sub writeallows { 1188: unless ($#extlinks>=0) { return; } 1189: my $thisurl = &Apache::lonnet::clutter(shift); 1190: if ($env{'httpref.'.$thisurl}) { 1191: $thisurl=$env{'httpref.'.$thisurl}; 1192: } 1193: my $thisdir=$thisurl; 1194: $thisdir=~s/\/[^\/]+$//; 1195: my %httpref=(); 1196: foreach (@extlinks) { 1197: $httpref{'httpref.'. 1198: &Apache::lonnet::hreflocation($thisdir,$_)}=$thisurl; 1199: } 1200: @extlinks=(); 1201: &Apache::lonnet::appenv(%httpref); 1202: } 1203: 1204: sub register_ssi { 1205: my ($url,%form)=@_; 1206: push (@Apache::lonxml::ssi_info,{'url'=>$url,'form'=>\%form}); 1207: return ''; 1208: } 1209: 1210: sub do_registered_ssi { 1211: foreach my $info (@Apache::lonxml::ssi_info) { 1212: my %form=%{ $info->{'form'}}; 1213: my $url=$info->{'url'}; 1214: &Apache::lonnet::ssi($url,%form); 1215: } 1216: } 1217: # 1218: # Afterburner handles anchors, highlights and links 1219: # 1220: sub afterburn { 1221: my $result=shift; 1222: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, 1223: ['highlight','anchor','link']); 1224: if ($env{'form.highlight'}) { 1225: foreach (split(/\,/,$env{'form.highlight'})) { 1226: my $anchorname=$_; 1227: my $matchthis=$anchorname; 1228: $matchthis=~s/\_+/\\s\+/g; 1229: $result=~s/(\Q$matchthis\E)/\<font color=\"red\"\>$1\<\/font\>/gs; 1230: } 1231: } 1232: if ($env{'form.link'}) { 1233: foreach (split(/\,/,$env{'form.link'})) { 1234: my ($anchorname,$linkurl)=split(/\>/,$_); 1235: my $matchthis=$anchorname; 1236: $matchthis=~s/\_+/\\s\+/g; 1237: $result=~s/(\Q$matchthis\E)/\<a href=\"$linkurl\"\>$1\<\/a\>/gs; 1238: } 1239: } 1240: if ($env{'form.anchor'}) { 1241: my $anchorname=$env{'form.anchor'}; 1242: my $matchthis=$anchorname; 1243: $matchthis=~s/\_+/\\s\+/g; 1244: $result=~s/(\Q$matchthis\E)/\<a name=\"$anchorname\"\>$1\<\/a\>/s; 1245: $result.=(<<"ENDSCRIPT"); 1246: <script type="text/javascript"> 1247: document.location.hash='$anchorname'; 1248: </script> 1249: ENDSCRIPT 1250: } 1251: return $result; 1252: } 1253: 1254: sub storefile { 1255: my ($file,$contents)=@_; 1256: &Apache::lonnet::correct_line_ends(\$contents); 1257: if (my $fh=Apache::File->new('>'.$file)) { 1258: print $fh $contents; 1259: $fh->close(); 1260: return 1; 1261: } else { 1262: &warning("Unable to save file $file"); 1263: return 0; 1264: } 1265: } 1266: 1267: sub createnewhtml { 1268: my $title=&mt('Title of document goes here'); 1269: my $body=&mt('Body of document goes here'); 1270: my $filecontents=(<<SIMPLECONTENT); 1271: <html> 1272: <head> 1273: <title>$title</title> 1274: </head> 1275: <body bgcolor="#FFFFFF"> 1276: $body 1277: </body> 1278: </html> 1279: SIMPLECONTENT 1280: return $filecontents; 1281: } 1282: 1283: sub createnewsty { 1284: my $filecontents=(<<SIMPLECONTENT); 1285: <definetag name=""> 1286: <render> 1287: <web></web> 1288: <tex></tex> 1289: </render> 1290: </definetag> 1291: SIMPLECONTENT 1292: return $filecontents; 1293: } 1294: 1295: 1296: sub inserteditinfo { 1297: my ($result,$filecontents,$filetype)=@_; 1298: $filecontents = &HTML::Entities::encode($filecontents,'<>&"'); 1299: # my $editheader='<a href="#editsection">Edit below</a><hr />'; 1300: my $xml_help = ''; 1301: my $initialize=''; 1302: if ($filetype eq 'html') { 1303: my $addbuttons=&Apache::lonhtmlcommon::htmlareaaddbuttons(); 1304: $initialize=&Apache::lonhtmlcommon::spellheader(); 1305: if (!&Apache::lonhtmlcommon::htmlareablocked() && 1306: &Apache::lonhtmlcommon::htmlareabrowser()) { 1307: $initialize.=(<<FULLPAGE); 1308: <script type="text/javascript"> 1309: $addbuttons 1310: 1311: HTMLArea.loadPlugin("FullPage"); 1312: 1313: function initDocument() { 1314: var editor=new HTMLArea("filecont",config); 1315: editor.registerPlugin(FullPage); 1316: editor.generate(); 1317: } 1318: </script> 1319: FULLPAGE 1320: } else { 1321: $initialize.=(<<FULLPAGE); 1322: <script type="text/javascript"> 1323: $addbuttons 1324: function initDocument() { 1325: } 1326: </script> 1327: FULLPAGE 1328: } 1329: $result=~s/\<body([^\>]*)\>/\<body onload="initDocument()" $1\>/i; 1330: $xml_help=&Apache::loncommon::helpLatexCheatsheet(); 1331: } 1332: my $cleanbut = ''; 1333: 1334: my $titledisplay=&display_title(); 1335: my %lt=&Apache::lonlocal::texthash('st' => 'Save and Edit', 1336: 'vi' => 'Save and View', 1337: 'dv' => 'Discard Edits and View', 1338: 'un' => 'undo', 1339: 'ed' => 'Edit'); 1340: my $buttons=(<<BUTTONS); 1341: $cleanbut 1342: <input type="submit" name="discardview" accesskey="d" value="$lt{'dv'}" /> 1343: <input type="submit" name="Undo" accesskey="u" value="$lt{'un'}" /><hr> 1344: <input type="submit" name="savethisfile" accesskey="s" value="$lt{'st'}" /> 1345: <input type="submit" name="viewmode" accesskey="v" value="$lt{'vi'}" /> 1346: BUTTONS 1347: $buttons.=&Apache::lonhtmlcommon::spelllink('xmledit','filecont'); 1348: my $editfooter=(<<ENDFOOTER); 1349: $initialize 1350: <hr /> 1351: <a name="editsection" /> 1352: <form method="post" name="xmledit"> 1353: $xml_help 1354: <input type="hidden" name="editmode" value="$lt{'ed'}" /> 1355: $buttons<br /> 1356: <textarea style="width:100%" cols="80" rows="44" name="filecont" id="filecont">$filecontents</textarea> 1357: <br />$buttons 1358: <br /> 1359: </form> 1360: $titledisplay 1361: </body> 1362: ENDFOOTER 1363: # $result=~s/(\<body[^\>]*\>)/$1$editheader/is; 1364: $result=~s/(\<\/body\>)/$editfooter/is; 1365: return $result; 1366: } 1367: 1368: sub get_target { 1369: my $viewgrades=&Apache::lonnet::allowed('vgr',$env{'request.course.id'}); 1370: if ( $env{'request.state'} eq 'published') { 1371: if ( defined($env{'form.grade_target'}) 1372: && ($viewgrades == 'F' )) { 1373: return ($env{'form.grade_target'}); 1374: } elsif (defined($env{'form.grade_target'})) { 1375: if (($env{'form.grade_target'} eq 'web') || 1376: ($env{'form.grade_target'} eq 'tex') ) { 1377: return $env{'form.grade_target'} 1378: } else { 1379: return 'web'; 1380: } 1381: } else { 1382: return 'web'; 1383: } 1384: } elsif ($env{'request.state'} eq 'construct') { 1385: if ( defined($env{'form.grade_target'})) { 1386: return ($env{'form.grade_target'}); 1387: } else { 1388: return 'web'; 1389: } 1390: } else { 1391: return 'web'; 1392: } 1393: } 1394: 1395: sub handler { 1396: my $request=shift; 1397: 1398: my $target=&get_target(); 1399: 1400: $Apache::lonxml::debug=$env{'user.debug'}; 1401: 1402: &Apache::loncommon::content_type($request,'text/html'); 1403: &Apache::loncommon::no_cache($request); 1404: if ($env{'request.state'} eq 'published') { 1405: $request->set_last_modified(&Apache::lonnet::metadata($request->uri, 1406: 'lastrevisiondate')); 1407: } 1408: $request->send_http_header; 1409: 1410: return OK if $request->header_only; 1411: 1412: 1413: my $file=&Apache::lonnet::filelocation("",$request->uri); 1414: my $filetype; 1415: if ($file =~ /\.sty$/) { 1416: $filetype='sty'; 1417: } else { 1418: $filetype='html'; 1419: } 1420: # 1421: # Edit action? Save file. 1422: # 1423: if (!($env{'request.state'} eq 'published')) { 1424: if ($env{'form.savethisfile'} || $env{'form.viewmode'} || $env{'form.Undo'}) { 1425: my $problem=&Apache::lonnet::getfile($file); 1426: my $error = &Apache::lonhomework::handle_save_or_undo($request, \$problem, \$env{'form.filecont'}); 1427: } 1428: } 1429: my %mystyle; 1430: my $result = ''; 1431: my $filecontents=&Apache::lonnet::getfile($file); 1432: if ($filecontents eq -1) { 1433: my $start_page=&Apache::loncommon::start_page('File Error'); 1434: my $end_page=&Apache::loncommon::end_page(); 1435: my $fnf=&mt('File not found'); 1436: $result=(<<ENDNOTFOUND); 1437: $start_page 1438: <b>$fnf: $file</b> 1439: $end_page 1440: ENDNOTFOUND 1441: $filecontents=''; 1442: if ($env{'request.state'} ne 'published') { 1443: if ($filetype eq 'sty') { 1444: $filecontents=&createnewsty(); 1445: } else { 1446: $filecontents=&createnewhtml(); 1447: } 1448: $env{'form.editmode'}='Edit'; #force edit mode 1449: } 1450: } else { 1451: unless ($env{'request.state'} eq 'published') { 1452: if ($filecontents=~/BEGIN LON-CAPA Internal/) { 1453: &Apache::lonxml::error(&mt('This file appears to be a rendering of a LON-CAPA resource. If this is correct, this resource will act very oddly and incorrectly.')); 1454: } 1455: # 1456: # we are in construction space, see if edit mode forced 1457: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, 1458: ['editmode']); 1459: } 1460: &Apache::lonnet::logthis("edit mode is ".$env{'form.editmode'}); 1461: if (!$env{'form.editmode'} || $env{'form.viewmode'} || $env{'form.discardview'}) { 1462: $result = &Apache::lonxml::xmlparse($request,$target,$filecontents, 1463: '',%mystyle); 1464: undef($Apache::lonhomework::parsing_a_task); 1465: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, 1466: ['rawmode']); 1467: if ($env{'form.rawmode'}) { $result = $filecontents; } 1468: } 1469: } 1470: 1471: # 1472: # Edit action? Insert editing commands 1473: # 1474: unless ($env{'request.state'} eq 'published') { 1475: if ($env{'form.editmode'} && (!($env{'form.viewmode'})) && (!($env{'form.discardview'}))) 1476: { 1477: my $displayfile=$request->uri; 1478: $displayfile=~s/^\/[^\/]*//; 1479: my %options = (); 1480: if ($env{'environment.remote'} ne 'off') { 1481: $options{'bgcolor'} = '#FFFFFF'; 1482: } 1483: my $start_page = &Apache::loncommon::start_page(undef,undef, 1484: \%options); 1485: $result=$start_page. 1486: &Apache::lonxml::message_location().'<h3>'. 1487: $displayfile. 1488: '</h3>'.&Apache::loncommon::end_page(); 1489: $result=&inserteditinfo($result,$filecontents,$filetype); 1490: } 1491: } 1492: if ($filetype eq 'html') { &writeallows($request->uri); } 1493: 1494: 1495: &Apache::lonxml::add_messages(\$result); 1496: $request->print($result); 1497: 1498: return OK; 1499: } 1500: 1501: sub display_title { 1502: my $result; 1503: if ($env{'request.state'} eq 'construct') { 1504: my $title=&Apache::lonnet::gettitle(); 1505: if (!defined($title) || $title eq '') { 1506: $title = $env{'request.filename'}; 1507: $title = substr($title, rindex($title, '/') + 1); 1508: } 1509: $result = "<script type='text/javascript'>top.document.title = '$title - LON-CAPA Construction Space';</script>"; 1510: } 1511: return $result; 1512: } 1513: 1514: sub debug { 1515: if ($Apache::lonxml::debug eq "1") { 1516: $|=1; 1517: my $request=$Apache::lonxml::request; 1518: if (!$request) { 1519: eval { $request=Apache->request; }; 1520: } 1521: if (!$request) { 1522: eval { $request=Apache2::RequestUtil->request; }; 1523: } 1524: $request->print('<font size="-2"><pre>DEBUG:'.&HTML::Entities::encode($_[0],'<>&"')."</pre></font>\n"); 1525: #&Apache::lonnet::logthis($_[0]); 1526: } 1527: } 1528: 1529: sub show_error_warn_msg { 1530: if ($env{'request.filename'} eq '/home/httpd/html/res/lib/templates/simpleproblem.problem' && 1531: &Apache::lonnet::allowed('mdc',$env{'request.course.id'})) { 1532: return 1; 1533: } 1534: return (($Apache::lonxml::debug eq 1) || 1535: ($env{'request.state'} eq 'construct') || 1536: ($Apache::lonhomework::browse eq 'F' 1537: && 1538: $env{'form.show_errors'} eq 'on')); 1539: } 1540: 1541: sub error { 1542: $errorcount++; 1543: if ( &show_error_warn_msg() ) { 1544: # If printing in construction space, put the error inside <pre></pre> 1545: push(@Apache::lonxml::error_messages, 1546: $Apache::lonxml::warnings_error_header. 1547: "<b>ERROR:</b>".join("<br />\n",@_)."<br />\n"); 1548: $Apache::lonxml::warnings_error_header=''; 1549: } else { 1550: my $errormsg; 1551: my ($symb)=&Apache::lonnet::symbread(); 1552: if ( !$symb ) { 1553: #public or browsers 1554: $errormsg=&mt("An error occured while processing this resource. The author has been notified."); 1555: } 1556: my $host=$Apache::lonnet::perlvar{'lonHostID'}; 1557: my $msg = join('<br />',(@_,"The error occurred on host <tt>$host</tt>")); 1558: #notify author 1559: &Apache::lonmsg::author_res_msg($env{'request.filename'},$msg); 1560: #notify course 1561: if ( $symb && $env{'request.course.id'} ) { 1562: my $cnum=$env{'course.'.$env{'request.course.id'}.'.num'}; 1563: my $cdom=$env{'course.'.$env{'request.course.id'}.'.domain'}; 1564: my (undef,%users)=&Apache::lonfeedback::decide_receiver(undef,0,1,1,1); 1565: my $declutter=&Apache::lonnet::declutter($env{'request.filename'}); 1566: my @userlist; 1567: foreach (keys %users) { 1568: my ($user,$domain) = split(/:/, $_); 1569: push(@userlist,"$user\@$domain"); 1570: my $key=$declutter.'_'.$user.'_'.$domain; 1571: my %lastnotified=&Apache::lonnet::get('nohist_xmlerrornotifications', 1572: [$key], 1573: $cdom,$cnum); 1574: my $now=time; 1575: if ($now-$lastnotified{$key}>86400) { 1576: &Apache::lonmsg::user_normal_msg($user,$domain, 1577: "Error [$declutter]",$msg); 1578: &Apache::lonnet::put('nohist_xmlerrornotifications', 1579: {$key => $now}, 1580: $cdom,$cnum); 1581: } 1582: } 1583: if ($env{'request.role.adv'}) { 1584: $errormsg=&mt("An error occured while processing this resource. The course personnel ([_1]) and the author have been notified.",join(', ',@userlist)); 1585: } else { 1586: $errormsg=&mt("An error occured while processing this resource. The instructor has been notified."); 1587: } 1588: } 1589: push(@Apache::lonxml::error_messages,"<b>$errormsg</b> <br />"); 1590: } 1591: } 1592: 1593: sub warning { 1594: $warningcount++; 1595: 1596: if ($env{'form.grade_target'} ne 'tex') { 1597: if ( &show_error_warn_msg() ) { 1598: push(@Apache::lonxml::warning_messages, 1599: $Apache::lonxml::warnings_error_header. 1600: "<b>W</b>ARNING<b>:</b>".join('<br />',@_)."<br />\n"); 1601: $Apache::lonxml::warnings_error_header=''; 1602: } 1603: } 1604: } 1605: 1606: sub info { 1607: if ($env{'form.grade_target'} ne 'tex' 1608: && $env{'request.state'} eq 'construct') { 1609: push(@Apache::lonxml::info_messages,join('<br />',@_)."<br />\n"); 1610: } 1611: } 1612: 1613: sub message_location { 1614: return '__LONCAPA_INTERNAL_MESSAGE_LOCATION__'; 1615: } 1616: 1617: sub add_messages { 1618: my ($msg)=@_; 1619: my $result=join(' ', 1620: @Apache::lonxml::info_messages, 1621: @Apache::lonxml::error_messages, 1622: @Apache::lonxml::warning_messages); 1623: undef(@Apache::lonxml::info_messages); 1624: undef(@Apache::lonxml::error_messages); 1625: undef(@Apache::lonxml::warning_messages); 1626: $$msg=~s/__LONCAPA_INTERNAL_MESSAGE_LOCATION__/$result/; 1627: $$msg=~s/__LONCAPA_INTERNAL_MESSAGE_LOCATION__//g; 1628: } 1629: 1630: sub get_param { 1631: my ($param,$parstack,$safeeval,$context,$case_insensitive) = @_; 1632: if ( ! $context ) { $context = -1; } 1633: my $args =''; 1634: if ( $#$parstack > (-2-$context) ) { $args=$$parstack[$context]; } 1635: if ( ! $Apache::lonxml::usestyle ) { 1636: $args=$Apache::lonxml::style_values.$args; 1637: } 1638: if ( ! $args ) { return undef; } 1639: if ( $case_insensitive ) { 1640: if ($args =~ s/(my (?:.*))(\$\Q$param\E[,\)])/$1.lc($2)/ei) { 1641: return &Apache::run::run("{$args;".'return $'.$param.'}', 1642: $safeeval); #' 1643: } else { 1644: return undef; 1645: } 1646: } else { 1647: if ( $args =~ /my .*\$\Q$param\E[,\)]/ ) { 1648: return &Apache::run::run("{$args;".'return $'.$param.'}', 1649: $safeeval); #' 1650: } else { 1651: return undef; 1652: } 1653: } 1654: } 1655: 1656: sub get_param_var { 1657: my ($param,$parstack,$safeeval,$context,$case_insensitive) = @_; 1658: if ( ! $context ) { $context = -1; } 1659: my $args =''; 1660: if ( $#$parstack > (-2-$context) ) { $args=$$parstack[$context]; } 1661: if ( ! $Apache::lonxml::usestyle ) { 1662: $args=$Apache::lonxml::style_values.$args; 1663: } 1664: &Apache::lonxml::debug("Args are $args param is $param"); 1665: if ($case_insensitive) { 1666: if (! ($args=~s/(my (?:.*))(\$\Q$param\E[,\)])/$1.lc($2)/ei)) { 1667: return undef; 1668: } 1669: } elsif ( $args !~ /my .*\$\Q$param\E[,\)]/ ) { return undef; } 1670: my $value=&Apache::run::run("{$args;".'return $'.$param.'}',$safeeval); #' 1671: &Apache::lonxml::debug("first run is $value"); 1672: if ($value =~ /^[\$\@\%][a-zA-Z_]\w*$/) { 1673: &Apache::lonxml::debug("doing second"); 1674: my @result=&Apache::run::run("return $value",$safeeval,1); 1675: if (!defined($result[0])) { 1676: return $value 1677: } else { 1678: if (wantarray) { return @result; } else { return $result[0]; } 1679: } 1680: } else { 1681: return $value; 1682: } 1683: } 1684: 1685: sub register_insert { 1686: my @data = split /\n/, &Apache::lonnet::getfile('/home/httpd/lonTabs/insertlist.tab'); 1687: my $i; 1688: my $tagnum=0; 1689: my @order; 1690: for ($i=0;$i < $#data; $i++) { 1691: my $line = $data[$i]; 1692: if ( $line =~ /^\#/ || $line =~ /^\s*\n/) { next; } 1693: if ( $line =~ /TABLE/ ) { last; } 1694: my ($tag,$descrip,$color,$function,$show,$helpfile,$helpdesc) = split(/,/, $line); 1695: if ($tag) { 1696: $insertlist{"$tagnum.tag"} = $tag; 1697: $insertlist{"$tagnum.description"} = $descrip; 1698: $insertlist{"$tagnum.color"} = $color; 1699: $insertlist{"$tagnum.function"} = $function; 1700: if (!defined($show)) { $show='yes'; } 1701: $insertlist{"$tagnum.show"}= $show; 1702: $insertlist{"$tagnum.helpfile"} = $helpfile; 1703: $insertlist{"$tagnum.helpdesc"} = $helpdesc; 1704: $insertlist{"$tag.num"}=$tagnum; 1705: $tagnum++; 1706: } 1707: } 1708: $i++; #skipping TABLE line 1709: $tagnum = 0; 1710: for (;$i < $#data;$i++) { 1711: my $line = $data[$i]; 1712: my ($mnemonic,@which) = split(/ +/,$line); 1713: my $tag = $insertlist{"$tagnum.tag"}; 1714: for (my $j=0;$j <=$#which;$j++) { 1715: if ( $which[$j] eq 'Y' ) { 1716: if ($insertlist{"$j.show"} ne 'no') { 1717: push(@{ $insertlist{"$tag.which"} },$j); 1718: } 1719: } 1720: } 1721: $tagnum++; 1722: } 1723: } 1724: 1725: sub description { 1726: my ($token)=@_; 1727: my $tagnum; 1728: my $tag=$token->[1]; 1729: foreach my $namespace (reverse @Apache::lonxml::namespace) { 1730: my $testtag=$namespace.'::'.$tag; 1731: $tagnum=$insertlist{"$testtag.num"}; 1732: if (defined($tagnum)) { last; } 1733: } 1734: if (!defined ($tagnum)) { $tagnum=$Apache::lonxml::insertlist{"$tag.num"}; } 1735: return $insertlist{$tagnum.'.description'}; 1736: } 1737: 1738: # Returns a list containing the help file, and the description 1739: sub helpinfo { 1740: my ($token)=@_; 1741: my $tagnum; 1742: my $tag=$token->[1]; 1743: foreach my $namespace (reverse @Apache::lonxml::namespace) { 1744: my $testtag=$namespace.'::'.$tag; 1745: $tagnum=$insertlist{"$testtag.num"}; 1746: if (defined($tagnum)) { last; } 1747: } 1748: if (!defined ($tagnum)) { $tagnum=$Apache::lonxml::insertlist{"$tag.num"}; } 1749: return ($insertlist{$tagnum.'.helpfile'}, $insertlist{$tagnum.'.helpdesc'}); 1750: } 1751: 1752: 1; 1753: __END__ 1754: 1755: