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