--- loncom/xml/lonxml.pm 2010/08/07 19:23:56 1.512 +++ loncom/xml/lonxml.pm 2024/04/17 15:15:13 1.572 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA -# XML Parser Module +# XML Parser Module # -# $Id: lonxml.pm,v 1.512 2010/08/07 19:23:56 raeburn Exp $ +# $Id: lonxml.pm,v 1.572 2024/04/17 15:15:13 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -25,13 +25,13 @@ # # http://www.lon-capa.org/ # -# Copyright for TtHfunc and TtMfunc by Ian Hutchinson. -# TtHfunc and TtMfunc (the "Code") may be compiled and linked into -# binary executable programs or libraries distributed by the -# Michigan State University (the "Licensee"), but any binaries so +# Copyright for TtHfunc and TtMfunc by Ian Hutchinson. +# TtHfunc and TtMfunc (the "Code") may be compiled and linked into +# binary executable programs or libraries distributed by the +# Michigan State University (the "Licensee"), but any binaries so # distributed are hereby licensed only for use in the context -# of a program or computational system for which the Licensee is the -# primary author or distributor, and which performs substantial +# of a program or computational system for which the Licensee is the +# primary author or distributor, and which performs substantial # additional tasks beyond the translation of (La)TeX into HTML. # The C source of the Code may not be distributed by the Licensee # to any other parties under any circumstances. @@ -57,7 +57,7 @@ described at http://www.lon-capa.org. -package Apache::lonxml; +package Apache::lonxml; use vars qw(@pwd @outputstack $redirection $import @extlinks $metamode $evaluate %insertlist @namespace $errorcount $warningcount); use strict; @@ -69,6 +69,8 @@ use Safe(); use Safe::Hole(); use Math::Cephes(); use Math::Random(); +use Math::Calculus::Expression(); +use Number::FormatEng(); use Opcode(); use POSIX qw(strftime); use Time::HiRes qw( gettimeofday tv_interval ); @@ -112,8 +114,10 @@ use Apache::lonmaxima(); use Apache::lonr(); use Apache::lonlocal; use Apache::lonhtmlcommon(); +use Apache::functionplotresponse(); +use Apache::lonnavmaps(); -#==================================== Main subroutine: xmlparse +#==================================== Main subroutine: xmlparse #debugging control, to turn on debugging modify the correct handler @@ -142,7 +146,7 @@ $metamode = 0; # turns on and of run::evaluate actually derefencing var refs $evaluate = 1; -# data structure for eidt mode, determines what tags can go into what other tags +# data structure for edit mode, determines what tags can go into what other tags %insertlist=(); # stores the list of active tag namespaces @@ -204,13 +208,17 @@ sub xmlend { if ($Apache::lonhomework::parsing_a_problem || $Apache::lonhomework::parsing_a_task ) { $mode='problem'; - $status=$Apache::inputtags::status[-1]; + $status=$Apache::inputtags::status[-1]; } my $discussion; &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, ['LONCAPA_INTERNAL_no_discussion']); - if (! exists($env{'form.LONCAPA_INTERNAL_no_discussion'}) || - $env{'form.LONCAPA_INTERNAL_no_discussion'} ne 'true') { + if ( + ( (!exists($env{'form.LONCAPA_INTERNAL_no_discussion'})) + || ($env{'form.LONCAPA_INTERNAL_no_discussion'} ne 'true') + ) + && ($env{'form.inhibitmenu'} ne 'yes') + ) { $discussion=&Apache::lonfeedback::list_discussion($mode,$status); } if ($target eq 'tex') { @@ -223,11 +231,10 @@ sub xmlend { } sub printalltags { - my $temp; - foreach $temp (sort keys %Apache::lonxml::alltags) { - &Apache::lonxml::debug("$temp -- ". - join(',',@{ $Apache::lonxml::alltags{$temp} })); - } + foreach my $temp (sort(keys(%Apache::lonxml::alltags))) { + &Apache::lonxml::debug("$temp -- ". + join(',',@{ $Apache::lonxml::alltags{$temp} })); + } } sub xmlparse { @@ -300,12 +307,17 @@ sub xmlparse { &clean_safespace($safeeval); if (@script_var_displays) { - $finaloutput .= join('',@script_var_displays); + if ($finaloutput =~ m{\s*\s*$}s) { + my $scriptoutput = join('',@script_var_displays); + $finaloutput=~s{(\s*)\s*$}{$scriptoutput$1}s; + } else { + $finaloutput .= join('',@script_var_displays); + } undef(@script_var_displays); } &init_state(); if ($env{'form.return_only_error_and_warning_counts'}) { - if ($env{'request.filename'}=~/\.(html|htm|xml)$/i) { + if ($env{'request.filename'}=~/\.(html|htm|xml)$/i) { my $error=&verify_html($content_file_string); if ($error) { $errorcount++; } } @@ -331,13 +343,13 @@ sub latex_special_symbols { $string=~s/([^\\])\&/$1\\\&/g; $string=~s/([^\\])\#/$1\\\#/g; $string =~ s/_/\\_/g; # _ -> \_ - $string =~ s/\^/\\\^{}/g; # ^ -> \^{} + $string =~ s/\^/\\\^{}/g; # ^ -> \^{} } else { $string=~s/\\/\\ensuremath{\\backslash}/g; $string=~s/\\\%|\%/\\\%/g; - $string=~s/\\{|{/\\{/g; + $string=~s/\\\{|\{/\\{/g; $string=~s/\\}|}/\\}/g; - $string=~s/\\ensuremath\\{\\backslash\\}/\\ensuremath{\\backslash}/g; + $string=~s/\\ensuremath\\\{\\backslash\\}/\\ensuremath{\\backslash}/g; $string=~s/\\\$|\$/\\\$/g; $string=~s/\\\_|\_/\\\_/g; $string=~s/([^\\]|^)(\~|\^)/$1\\$2\\strut /g; @@ -358,6 +370,8 @@ sub inner_xmlparse { my $result; my $token; my $dontpop=0; + my $lastdontpop; + my $lastendtag; my $startredirection = $Apache::lonxml::redirection; while ( $#$pars > -1 ) { while ($token = $$pars['-1']->get_token) { @@ -453,17 +467,29 @@ sub inner_xmlparse { } $result = ''; - if ($token->[0] eq 'E' && !$dontpop) { - &end_tag($stack,$parstack,$token); + if ($token->[0] eq 'E') { + if ($dontpop) { + $lastdontpop = $token; + } else { + $lastendtag = $token->[1]; + &end_tag($stack,$parstack,$token); + } } $dontpop=0; - } + } if ($#$pars > -1) { pop @$pars; pop @Apache::lonxml::pwd; } } + if (($#$stack == 0) && ($stack->[0] eq 'physnet') && ($target eq 'web') && + ($lastendtag eq 'LONCAPA_INTERNAL_TURN_STYLE_ON')) { + if ((ref($lastdontpop) eq 'ARRAY') && ($lastdontpop->[1] eq 'physnet')) { + &end_tag($stack,$parstack,$lastdontpop); + } + } + # if ($target eq 'meta') { # $finaloutput.=&endredirection; # } @@ -480,11 +506,11 @@ sub inner_xmlparse { if ($target eq 'modified') { # if modfied, handle startpart and endpart $finaloutput=~s/\]*\>(.*)\]*\>/$1<\/part>/gs; - } + } return $finaloutput; } -## +## ## Looks to see if there is a subroutine defined for this tag. If so, call it, ## otherwise do not call it as we do not know what it is. ## @@ -571,7 +597,7 @@ sub callsub { sub init_state { undef(%state); } - + sub set_state { my ($key,$value) = @_; $state{$key} = $value; @@ -642,9 +668,9 @@ sub setup_globals { sub init_safespace { my ($target,$safeeval,$safehole,$safeinit) = @_; - $safeeval->reval('use Math::Complex;'); $safeeval->reval('use LaTeX::Table;'); $safeeval->deny_only(':dangerous'); + $safeeval->reval('use LONCAPA::LCMathComplex;'); $safeeval->permit_only(":default"); $safeeval->permit("entereval"); $safeeval->permit(":base_math"); @@ -673,7 +699,7 @@ sub init_safespace { $safehole->wrap(\&Apache::lonr::r_check,$safeeval,'&r_check'); $safehole->wrap(\&Apache::lonr::r_cas_formula_fix,$safeeval, '&r_cas_formula_fix'); - + $safehole->wrap(\&Apache::caparesponse::capa_formula_fix,$safeeval, '&capa_formula_fix'); @@ -699,7 +725,7 @@ sub init_safespace { $safehole->wrap(\&Math::Cephes::y1,$safeeval,'&y1'); $safehole->wrap(\&Math::Cephes::yn,$safeeval,'&yn'); $safehole->wrap(\&Math::Cephes::yv,$safeeval,'&yv'); - + $safehole->wrap(\&Math::Cephes::bdtr ,$safeeval,'&bdtr' ); $safehole->wrap(\&Math::Cephes::bdtrc ,$safeeval,'&bdtrc' ); $safehole->wrap(\&Math::Cephes::bdtri ,$safeeval,'&bdtri' ); @@ -787,6 +813,18 @@ sub init_safespace { $safehole->wrap(\&Apache::lonnet::logthis,$safeeval,'&LONCAPA_INTERNAL_LOGTHIS'); $safehole->wrap(\&Apache::inputtags::finalizeawards,$safeeval,'&LONCAPA_INTERNAL_FINALIZEAWARDS'); $safehole->wrap(\&Apache::caparesponse::get_sigrange,$safeeval,'&LONCAPA_INTERNAL_get_sigrange'); + $safehole->wrap(\&Apache::functionplotresponse::fpr_val,$safeeval,'&fpr_val'); + $safehole->wrap(\&Apache::functionplotresponse::fpr_f,$safeeval,'&fpr_f'); + $safehole->wrap(\&Apache::functionplotresponse::fpr_dfdx,$safeeval,'&fpr_dfdx'); + $safehole->wrap(\&Apache::functionplotresponse::fpr_d2fdx2,$safeeval,'&fpr_d2fdx2'); + $safehole->wrap(\&Apache::functionplotresponse::fpr_vectorcoords,$safeeval,'&fpr_vectorcoords'); + $safehole->wrap(\&Apache::functionplotresponse::fpr_objectcoords,$safeeval,'&fpr_objectcoords'); + $safehole->wrap(\&Apache::functionplotresponse::fpr_vectorlength,$safeeval,'&fpr_vectorlength'); + $safehole->wrap(\&Apache::functionplotresponse::fpr_vectorangle,$safeeval,'&fpr_vectorangle'); + $safehole->wrap(\&Math::Calculus::Expression::math_calculus_expression,$safeeval,'&math_calculus_expression'); + $safehole->wrap(\&Number::FormatEng::format_eng,$safeeval,'&number_format_eng'); + $safehole->wrap(\&Number::FormatEng::format_pref,$safeeval,'&number_format_pref'); + # use Data::Dumper; # $safehole->wrap(\&Data::Dumper::Dumper,$safeeval,'&LONCAPA_INTERNAL_Dumper'); #need to inspect this class of ops @@ -794,7 +832,10 @@ sub init_safespace { $safeeval->permit("require"); $safeinit .= ';$external::target="'.$target.'";'; &Apache::run::run($safeinit,$safeeval); - &initialize_rndseed($safeeval); + my $rawrndseed = &initialize_rndseed($safeeval); + if ($target eq 'grade') { + $Apache::lonhomework::rawrndseed = $rawrndseed; + } } sub clean_safespace { @@ -833,12 +874,14 @@ sub initialize_rndseed { my $safeinit = '$external::randomseed="'.$rndseed.'";'; &Apache::lonxml::debug("Setting rndseed to $rndseed"); &Apache::run::run($safeinit,$safeeval); + return $rndseed; } sub default_homework_load { my ($safeeval)=@_; &Apache::lonxml::debug('Loading default_homework'); - my $default=&Apache::lonnet::getfile('/home/httpd/html/res/adm/includes/default_homework.lcpm'); + my $default=&Apache::lonnet::getfile($Apache::lonnet::perlvar{'lonIncludes'}. + '/default_homework.lcpm'); if ($default eq -1) { &Apache::lonxml::error("Unable to find default_homework.lcpm"); } else { @@ -953,7 +996,7 @@ sub decreasedepth { sub get_id { my ($parstack,$safeeval)=@_; my $id= &Apache::lonxml::get_param('id',$parstack,$safeeval); - if ($env{'request.state'} eq 'construct' && $id =~ /([._]|[^\w\d\s[:punct:]])/) { + if ($env{'request.state'} eq 'construct' && $id =~ /([._]|[^\w\s\-])/) { &error(&mt('ID [_1] contains invalid characters. IDs are only allowed to contain letters, numbers, spaces and -','"'.$id.'"')); } if ($id =~ /^\s*$/) { $id = $Apache::lonxml::curdepth; } @@ -1008,7 +1051,7 @@ the current 'bubble line number' is stor The value of it is stored in $Apache:lonxml::counter when live and stored back to env after done. -=item &increment_counter($increment); +=item &increment_counter($increment, $part_response); Increments the internal counter environment variable a specified amount @@ -1029,7 +1072,7 @@ sub increment_counter { } $Apache::lonxml::counter += $increment; - # If the caller supplied the response_id parameter, + # If the caller supplied the response_id parameter, # Maintain its counter.. creating if necessary. if (defined($part_response)) { @@ -1150,7 +1193,7 @@ sub set_bubble_lines { =item get_bubble_line_hash -Returns the current bubble line hash. This is assumed to +Returns the current bubble line hash. This is assumed to be small so we return a copy @@ -1176,8 +1219,8 @@ sub get_all_text { my $depth=0; my $token; my $result=''; - if ( $tag =~ m:^/: ) { - my $tag=substr($tag,1); + if ( $tag =~ m:^/: ) { + my $tag=substr($tag,1); #&Apache::lonxml::debug("have:$tag:"); my $top_empty=0; while (($depth >=0) && ($#$pars > -1) && (!$top_empty)) { @@ -1278,7 +1321,7 @@ sub newparser { push (@Apache::lonxml::pwd, $Apache::lonxml::pwd[$#Apache::lonxml::pwd]); } else { push (@Apache::lonxml::pwd, $dir); - } + } } sub parstring { @@ -1295,7 +1338,7 @@ sub parstring { push(@values,"\"$val\""); } } - my $var_init = + my $var_init = (@vars) ? 'my ('.join(',',@vars).') = ('.join(',',@values).');' : ''; return $var_init; @@ -1306,7 +1349,7 @@ sub extlink { if (!$exact) { $res=&Apache::lonnet::hreflocation($Apache::lonxml::pwd[-1],$res); } - push(@Apache::lonxml::extlinks,$res) + push(@Apache::lonxml::extlinks,$res); } sub writeallows { @@ -1342,7 +1385,9 @@ sub do_registered_ssi { sub add_script_result { my ($display) = @_; - push(@script_var_displays, $display); + if ($display ne '') { + push(@script_var_displays, $display); + } } # @@ -1434,17 +1479,27 @@ SIMPLECONTENT sub verify_html { my ($filecontents)=@_; - if ($filecontents!~/(?:\<|\<\;)(?:html|xml)[^\<]*(?:\>|\>\;)/is) { - return &mt('File does not have [_1] or [_2] starting tag','<html>','<xml>'); - } - if ($filecontents!~/(?:\<|\<\;)\/(?:html|xml)(?:\>|\>\;)/is) { - return &mt('File does not have [_1] or [_2] ending tag','<html>','<xml>'); - } - if ($filecontents!~/(?:\<|\<\;)(?:body|frameset)[^\<]*(?:\>|\>\;)/is) { - return &mt('File does not have [_1] or [_2] starting tag','<body>','<frameset>'); - } - if ($filecontents!~/(?:\<|\<\;)\/(?:body|frameset)[^\<]*(?:\>|\>\;)/is) { - return &mt('File does not have [_1] or [_2] ending tag','<body>','<frameset>'); + my ($is_html,$is_xml,$is_physnet); + if ($filecontents =~/(?:\<|\<\;)\?xml[^\<]*\?(?:\>|\>\;)/is) { + $is_xml = 1; + } elsif ($filecontents =~/(?:\<|\<\;)html(?:\s+[^\<]+|\s*)(?:\>|\>\;)/is) { + $is_html = 1; + } elsif ($filecontents =~/(?:\<|\<\;)physnet[^\<]*(?:\>|\>\;)/is) { + $is_physnet = 1; + } + unless ($is_xml || $is_html || $is_physnet) { + return &mt('File does not have [_1] or [_2] starting tag','<html>','<?xml ?>'); + } + if ($is_html) { + if ($filecontents!~/(?:\<|\<\;)\/html(?:\>|\>\;)/is) { + return &mt('File does not have [_1] ending tag','<html>'); + } + if ($filecontents!~/(?:\<|\<\;)(?:body|frameset)[^\<]*(?:\>|\>\;)/is) { + return &mt('File does not have [_1] or [_2] starting tag','<body>','<frameset>'); + } + if ($filecontents!~/(?:\<|\<\;)\/(?:body|frameset)[^\<]*(?:\>|\>\;)/is) { + return &mt('File does not have [_1] or [_2] ending tag','<body>','<frameset>'); + } } return ''; } @@ -1477,56 +1532,90 @@ sub renderingoptions { {&Apache::lonlocal::texthash ('' => '', 'tth' => 'tth (TeX to HTML)', - 'jsMath' => 'jsMath', + 'MathJax' => 'MathJax', 'mimetex' => 'mimetex (Convert to Images)')}). ''; return $output; } sub inserteditinfo { - my ($filecontents, $filetype, $filename)=@_; + my ($filecontents,$filetype,$filename,$symb,$itemtitle,$folderpath,$uri,$action) = @_; $filecontents = &HTML::Entities::encode($filecontents,'<>&"'); my $xml_help = ''; my $initialize=''; my $textarea_id = 'filecont'; - my $dragmath_button; - my ($add_to_onload, $add_to_onresize); + my ($dragmath_button,$deps_button,$context,$cnum,$cdom,$add_to_onload, + $add_to_onresize,$init_dragmath); $initialize=&Apache::lonhtmlcommon::spellheader(); - if (($filetype eq 'html') && (&Apache::lonhtmlcommon::htmlareabrowser())) { - my $lang = &Apache::lonhtmlcommon::htmlarea_lang(); - my %textarea_args = ( - fullpage => 'true', - dragmath => 'math', - ); - $initialize .= - &Apache::lonhtmlcommon::htmlareaselectactive(\%textarea_args). - (< 'true', + dragmath => 'math', + ); + $initialize .= &Apache::lonhtmlcommon::htmlareaselectactive(\%textarea_args); + if ($context eq 'syllabus') { + $init_dragmath = "editmath_visibility('filecont','none')"; + } + } + } + $initialize .= (< +// FULLPAGE + my $textareaclass; + if ($filetype eq 'html') { + if ($context eq 'syllabus') { + $deps_button = &Apache::lonhtmlcommon::dependencies_button()."\n"; + $initialize .= + &Apache::lonhtmlcommon::dependencycheck_js(undef,&mt('Syllabus'), + $uri,undef, + "/public/$cdom/$cnum/syllabus"). + "\n"; + if (&Apache::lonhtmlcommon::htmlareabrowser()) { + $textareaclass = 'class="LC_richDefaultOn"'; + } + } elsif ($symb || $folderpath) { + $deps_button = &Apache::lonhtmlcommon::dependencies_button()."\n"; + $initialize .= + &Apache::lonhtmlcommon::dependencycheck_js($symb,$itemtitle, + undef,$folderpath,$uri)."\n"; + } + $dragmath_button = ''.&Apache::lonhtmlcommon::dragmath_button('filecont',1).''; + $initialize .= "\n".&Apache::lonhtmlcommon::dragmath_js('EditMathPopup'); } - if ($filetype eq 'html' || $filetype eq 'tex') { - $dragmath_button = '
'.&Apache::lonhtmlcommon::dragmath_button('filecont',1).'
'; - $initialize .= "\n".&Apache::lonhtmlcommon::dragmath_js('EditMathPopup'); - } - $add_to_onload = 'initDocument();'; $add_to_onresize = "resize_textarea('$textarea_id','LC_aftertextarea');"; if ($filetype eq 'html') { - $xml_help=&Apache::loncommon::helpLatexCheatsheet(); + my $not_author; + if ($uri =~ m{^/uploaded/}) { + $not_author = 1; + } + $xml_help=&Apache::loncommon::helpLatexCheatsheet(undef,undef,$not_author); } my $titledisplay=&display_title(); - my $textareaclass; my %lt=&Apache::lonlocal::texthash('st' => 'Save and Edit', 'vi' => 'Save and View', 'dv' => 'Discard Edits and View', - 'un' => 'undo', - 'ed' => 'Edit'); + 'un' => 'Undo', + 'ed' => 'Edit', + 'ew' => 'Edit with Daxe'); my $spelllink = &Apache::lonhtmlcommon::spelllink('xmledit','filecont'); my $textarea_events = &Apache::edit::element_change_detection(); my $form_events = &Apache::edit::form_change_detection(); @@ -1534,16 +1623,38 @@ FULLPAGE if ($filetype eq 'html') { $htmlerror=&verify_html($filecontents); if ($htmlerror) { - $htmlerror=''.$htmlerror.''; + $htmlerror=(' 'x3).' '.$htmlerror.''; } if (&Apache::lonhtmlcommon::htmlareabrowser()) { - $textareaclass = 'class="LC_richDetectHtml"'; + unless ($textareaclass) { + $textareaclass = 'class="LC_richDefaultOff"'; + } + } + } + my ($undo,$daxebutton,%onclick); + foreach my $item ('discard','undo','daxe') { + $onclick{$item} = 'onclick="still_ask=true;setmode(this.form,'."'$item'".')"'; + } + foreach my $item ('saveedit','saveview') { + $onclick{$item} = 'onclick="is_submit=true;setmode(this.form,'."'$item'".')"'; + } + unless ($uri =~ m{^/uploaded/}) { + $undo = ''."\n"; + } + $initialize .= &setmode_javascript(); + if ($filetype eq 'html') { + my %editors = &Apache::loncommon::permitted_editors(); + if ($editors{'daxe'}) { + $daxebutton = ''."\n"; } } my $editfooter=(< -
+ +
$filename @@ -1551,26 +1662,113 @@ $initialize $xml_help
-
- - - $spelllink $htmlerror +
+ +
-
- - +
+ + $undo $deps_button $daxebutton $dragmath_button $htmlerror
-$dragmath_button - +
$spelllink

$titledisplay
- ENDFOOTER - return ($editfooter,$add_to_onload,$add_to_onresize);; + return ($editfooter,$add_to_onload,$add_to_onresize); +} + +sub setmode_javascript { + return <<"ENDSCRIPT"; + +ENDSCRIPT +} + +sub seteditor_javascript { + my ($is_course_doc,$is_supp,$supp_path,$supp_title) = @_; + my $symb; + if ($is_course_doc) { + if (!$is_supp) { + ($symb) = &Apache::lonnet::whichuser(); + if ($symb) { + $symb = &escape($symb); + } + } + } + return <<"ENDSCRIPT"; + +ENDSCRIPT } sub get_target { @@ -1605,7 +1803,7 @@ sub handler { my $target=&get_target(); $Apache::lonxml::debug=$env{'user.debug'}; - + &Apache::loncommon::content_type($request,'text/html'); &Apache::loncommon::no_cache($request); if ($env{'request.state'} eq 'published') { @@ -1613,7 +1811,7 @@ sub handler { 'lastrevisiondate')); } # Embedded Flash movies from Camtasia served from https will not display in IE - # if XML config file has expired from cache. + # if XML config file has expired from cache. if ($ENV{'SERVER_PORT'} == 443) { if ($request->uri =~ /\.xml$/) { my ($httpbrowser,$clientbrowser) = @@ -1628,7 +1826,7 @@ sub handler { } } $request->send_http_header; - + return OK if $request->header_only; @@ -1639,6 +1837,24 @@ sub handler { } else { $filetype='html'; } + unless ($env{'request.uri'}) { + $env{'request.uri'}=$request->uri; + &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, + ['todocs']); + } + my ($cdom,$cnum); + if ($env{'request.course.id'}) { + $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + if ($filetype eq 'html') { + if ($request->uri =~ m{^\Q/uploaded/$cdom/$cnum/portfolio/syllabus/\E.+$}) { + if (&Apache::lonnet::allowed('mdc',$env{'request.course.id'})) { + &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, + ['editmode']); + } + } + } + } if ($filetype eq 'sty') { $breadcrumbtext = 'Style File Editor'; } elsif ($filetype eq 'js') { @@ -1657,14 +1873,17 @@ sub handler { # Edit action? Save file. # if (!($env{'request.state'} eq 'published')) { - if ($env{'form.savethisfile'} || $env{'form.viewmode'} || $env{'form.Undo'}) { + if (($env{'form.problemmode'} eq 'saveedit') || + ($env{'form.problemmode'} eq 'saveview') || + ($env{'form.problemmode'} eq 'undo')) { my $html_file=&Apache::lonnet::getfile($file); my $error = &Apache::lonhomework::handle_save_or_undo($request, \$html_file, \$env{'form.filecont'}); - if ($env{'form.savethisfile'}) { - $env{'form.editmode'}='Edit'; #force edit mode + if ($env{'form.problemmode'} eq 'saveedit') { + $env{'form.editmode'}='edit'; #force edit mode } } } + my $inhibit_menu; my %mystyle; my $result = ''; my $filecontents=&Apache::lonnet::getfile($file); @@ -1689,7 +1908,7 @@ ENDNOTFOUND } elsif ($filetype ne 'css' && $filetype ne 'txt' && $filetype ne 'tex') { $filecontents=&createnewhtml(); } - $env{'form.editmode'}='Edit'; #force edit mode + $env{'form.editmode'}='edit'; #force edit mode } } else { unless ($env{'request.state'} eq 'published') { @@ -1701,7 +1920,9 @@ ENDNOTFOUND &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, ['editmode']); } - if (!$env{'form.editmode'} || $env{'form.viewmode'} || $env{'form.discardview'}) { + if ((!$env{'form.editmode'}) || + ($env{'form.problemmode'} eq 'saveview') || + ($env{'form.problemmode'} eq 'discard')) { if ($filetype eq 'html' || $filetype eq 'sty') { &Apache::structuretags::reset_problem_globals(); $result = &Apache::lonxml::xmlparse($request,$target, @@ -1714,9 +1935,6 @@ ENDNOTFOUND $result = &Apache::lontexconvert::converted(\$filecontents, $env{'form.texengine'}); if ($env{'form.return_only_error_and_warning_counts'}) { - if (&verify_html(''.$result.'')) { - $errorcount++; - } $result = "$errorcount:$warningcount"; } } else { @@ -1725,8 +1943,15 @@ ENDNOTFOUND &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, ['rawmode']); if ($env{'form.rawmode'}) { $result = $filecontents; } - if (($filetype ne 'html') && - (!$env{'form.return_only_error_and_warning_counts'})) { + if (($env{'request.state'} eq 'construct') && + (($filetype eq 'css') || ($filetype eq 'js')) && ($ENV{'HTTP_REFERER'})) { + if ($ENV{'HTTP_REFERER'} =~ m{^https?\://[^\/]+/priv/$LONCAPA::match_domain/$LONCAPA::match_username/[^\?]+\.(x?html?|swf)(|\?)[^\?]*$}) { + $inhibit_menu = 1; + } + } + if (($filetype ne 'html') && + (!$env{'form.return_only_error_and_warning_counts'}) && + (!$inhibit_menu)) { my $nochgview = 1; my $controls = ''; if ($env{'request.state'} eq 'construct') { @@ -1743,8 +1968,17 @@ ENDNOTFOUND } my $brcrum; if ($env{'request.state'} eq 'construct') { - $brcrum = [{'href' => &Apache::loncommon::authorspace(), - 'text' => 'Construction Space'}, + my $text = 'Authoring Space'; + my $href = &Apache::loncommon::authorspace($request->uri); + if ($env{'request.course.id'}) { + my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + if ($href eq "/priv/$cdom/$cnum/") { + $text = 'Course Authoring Space'; + } + } + $brcrum = [{'href' => $href, + 'text' => $text,}, {'href' => '', 'text' => $breadcrumbtext}]; } else { @@ -1764,24 +1998,66 @@ ENDNOTFOUND # # Edit action? Insert editing commands # - unless ($env{'request.state'} eq 'published') { - if ($env{'form.editmode'} && (!($env{'form.viewmode'})) && (!($env{'form.discardview'}))) - { - my $displayfile=$request->uri; - $displayfile=~s/^\/[^\/]*//; + unless (($env{'request.state'} eq 'published') || ($inhibit_menu)) { + if (($env{'form.editmode'}) && + (!($env{'form.problemmode'} eq 'saveview')) && + (!($env{'form.problemmode'} eq 'discard'))) { + my ($displayfile,$url,$symb,$itemtitle,$action); + $displayfile=$request->uri; + if ($request->uri =~ m{^/uploaded/}) { + if ($env{'request.course.id'}) { + if ($request->uri =~ m{^\Q/uploaded/$cdom/$cnum/\E(docs|supplemental)/}) { + if ($1 eq 'supplemental') { + &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, + ['folderpath','title']); + } + if (($env{'request.state'} eq 'edit') && ($env{'form.editmode'} eq 'edit') && + ($filetype eq 'html')) { + &Apache::lonhtmlcommon::clear_breadcrumbs(); + } + } elsif ($request->uri =~ m{^\Q/uploaded/$cdom/$cnum/portfolio/syllabus/\E(.+)$}) { + my $filename = $1; + if ($1 eq 'loncapa.html') { + $displayfile = &mt('Syllabus (minimal template)'); + $action = $request->uri.'?forceedit=1'; + } else { + $displayfile = &mt('Syllabus file: [_1]',$1); + } + $itemtitle = &mt('Syllabus'); + } + } + unless ($itemtitle) { + ($symb,$itemtitle,$displayfile) = + &get_courseupload_hierarchy($request->uri, + $env{'form.folderpath'}, + $env{'form.title'}); + } + } else { + $displayfile=~s/^\/[^\/]*//; + } my ($edit_info, $add_to_onload, $add_to_onresize)= - &inserteditinfo($filecontents,$filetype,$displayfile); + &inserteditinfo($filecontents,$filetype,$displayfile,$symb, + $itemtitle,$env{'form.folderpath'},$request->uri,$action); - my %options = + my %options = ('add_entries' => {'onresize' => $add_to_onresize, 'onload' => $add_to_onload, }); my $header; if ($env{'request.state'} eq 'construct') { + my $text = 'Authoring Space'; + my $href = &Apache::loncommon::authorspace($request->uri); + if ($env{'request.course.id'}) { + my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + if ($href eq "/priv/$cdom/$cnum/") { + $text = 'Course Authoring Space'; + } + } $options{'bread_crumbs'} = [{ - 'href' => &Apache::loncommon::authorspace(), - 'text' => 'Construction Space'}, + 'href' => $href, + 'text' => $text}, {'href' => '', 'text' => $breadcrumbtext}]; $header = &Apache::loncommon::head_subbox( @@ -1803,7 +2079,7 @@ ENDNOTFOUND &Apache::lonxml::add_messages(\$result); $request->print($result); - + return OK; } @@ -1816,11 +2092,48 @@ sub display_title { $title = substr($title, rindex($title, '/') + 1); } $result = ""; + .&mt('Authoring Space')."';"; } return $result; } +sub get_courseupload_hierarchy { + my ($url,$folderpath,$title) = @_; + my ($symb,$itemtitle,$displaypath); + if ($env{'request.course.id'}) { + if ($folderpath =~ /^supplemental/) { + my @folders = split(/\&/,$folderpath); + my @pathitems; + while (@folders) { + my $folder=shift(@folders); + my $foldername=shift(@folders); + $foldername =~ s/\:(\d*)\:(\w*)\:(\w*):(\d*)\:?(\d*)$//; + push(@pathitems,&unescape($foldername)); + } + if ($title) { + push(@pathitems,&unescape($title)); + $itemtitle = $title; + } + $displaypath = join(' » ',@pathitems); + } else { + $symb = &Apache::lonnet::symbread($url); + my ($map,$id,$res)=&Apache::lonnet::decode_symb($symb); + my $navmap=Apache::lonnavmaps::navmap->new; + if (ref($navmap)) { + my $res = $navmap->getBySymb($symb); + if (ref($res)) { + my @pathitems = + &Apache::loncommon::get_folder_hierarchy($navmap,$map,1); + $itemtitle = $res->compTitle(); + push(@pathitems,$itemtitle); + $displaypath = join(' » ',@pathitems); + } + } + } + } + return ($symb,$itemtitle,$displaypath); +} + sub debug { if ($Apache::lonxml::debug eq "1") { $|=1; @@ -1837,8 +2150,9 @@ sub debug { } sub show_error_warn_msg { - if ($env{'request.filename'} eq '/home/httpd/html/res/lib/templates/simpleproblem.problem' && - &Apache::lonnet::allowed('mdc',$env{'request.course.id'})) { + if (($env{'request.filename'} eq + $Apache::lonnet::perlvar{'lonDocRoot'}.'/res/lib/templates/simpleproblem.problem') && + (&Apache::lonnet::allowed('mdc',$env{'request.course.id'}))) { return 1; } return (($Apache::lonxml::debug eq 1) || @@ -1900,9 +2214,9 @@ sub error { my $declutter=&Apache::lonnet::declutter($env{'request.filename'}); my $baseurl = &Apache::lonnet::clutter($declutter); my @userlist; - foreach (keys %users) { + foreach (keys(%users)) { my ($user,$domain) = split(/:/, $_); - push(@userlist,"$user\@$domain"); + push(@userlist,"$user:$domain"); my $key=$declutter.'_'.$user.'_'.$domain; my %lastnotified=&Apache::lonnet::get('nohist_xmlerrornotifications', [$key], @@ -1925,13 +2239,13 @@ sub error { $errormsg=&mt("An error occurred while processing this resource. The instructor has been notified."); } } - push(@Apache::lonxml::error_messages,"$errormsg
"); + push(@Apache::lonxml::error_messages,"$errormsg
"); } } sub warning { $warningcount++; - + if ($env{'form.grade_target'} ne 'tex') { if ( &show_error_warn_msg() ) { push(@Apache::lonxml::warning_messages, @@ -1946,7 +2260,7 @@ sub warning { } sub info { - if ($env{'form.grade_target'} ne 'tex' + if ($env{'form.grade_target'} ne 'tex' && $env{'request.state'} eq 'construct') { push(@Apache::lonxml::info_messages,join('
',@_)."
\n"); } @@ -1970,16 +2284,25 @@ sub add_messages { } sub get_param { - my ($param,$parstack,$safeeval,$context,$case_insensitive) = @_; + my ($param,$parstack,$safeeval,$context,$case_insensitive, $noelide) = @_; + if ( ! $context ) { $context = -1; } my $args =''; if ( $#$parstack > (-2-$context) ) { $args=$$parstack[$context]; } if ( ! $Apache::lonxml::usestyle ) { $args=$Apache::lonxml::style_values.$args; } + + + if ($noelide) { +# $args =~ s/\\'/'/g; + $args =~ s/'\$/'\\\$/g; + } + if ( ! $args ) { return undef; } if ( $case_insensitive ) { if ($args =~ s/(my (?:.*))(\$\Q$param\E[,\)])/$1.lc($2)/ei) { + return &Apache::run::run("{$args;".'return $'.$param.'}', $safeeval); #' } else { @@ -1987,6 +2310,7 @@ sub get_param { } } else { if ( $args =~ /my .*\$\Q$param\E[,\)]/ ) { + return &Apache::run::run("{$args;".'return $'.$param.'}', $safeeval); #' } else { @@ -2033,11 +2357,13 @@ sub register_insert_xml { while (my $token = $parser->get_token()) { if ($token->[0] eq 'S') { my $key; - if ($token->[1] eq 'tag') { + if ($token->[1] eq 'tag') { $tag = $token->[2]{'name'}; - $insertlist{"$tagnum.tag"} = $tag; - $insertlist{"$tag.num"} = $tagnum; - push(@alltags,$tag); + if (defined($tag)) { + $insertlist{$tagnum.'.tag'} = $tag; + $insertlist{$tag.'.num'} = $tagnum; + push(@alltags,$tag); + } } elsif ($in_help && $token->[1] eq 'file') { $key = $tag.'.helpfile'; } elsif ($in_help && $token->[1] eq 'description') { @@ -2066,15 +2392,15 @@ sub register_insert_xml { } } } - + # parse the allows and ignore tags set to no foreach my $tag (@alltags) { - next if (!exists($insertlist{"$tag.allow"})); - my $allow = $insertlist{"$tag.allow"}; + next if (!exists($insertlist{$tag.'.allow'})); + my $allow = $insertlist{$tag.'.allow'}; foreach my $element (split(',',$allow)) { $element =~ s/(^\s*|\s*$ )//gx; - if (!exists($insertlist{"$element.show"}) - || $insertlist{"$element.show"} ne 'no') { + if (!exists($insertlist{$element.'.show'}) + || $insertlist{$element.'.show'} ne 'no') { push(@{ $insertlist{$tag.'.which'} },$element); } } @@ -2088,7 +2414,7 @@ sub register_insert { sub dump_insertlist { my ($ext) = @_; - open(XML,">/tmp/insertlist.xml.$ext"); + open(XML,">","/tmp/insertlist.xml.$ext"); print XML (""); my $i=0; @@ -2146,7 +2472,7 @@ sub description { sub helpinfo { my ($token)=@_; my $tag = &get_tag($token); - return ($insertlist{$tag.'.helpfile'}, $insertlist{$tag.'.helpdesc'}); + return ($insertlist{$tag.'.helpfile'}, &mt($insertlist{$tag.'.helpdesc'})); } sub get_tag { @@ -2172,7 +2498,7 @@ sub get_tag { =item &print_pdf_radiobutton(fieldname, value) Returns a latexline to generate a PDF-Form-Radiobutton. -Note: Radiobuttons with equal names are automaticly grouped +Note: Radiobuttons with equal names are automaticly grouped in a selection-group. $fieldname: PDF internalname of the radiobutton(group) @@ -2199,7 +2525,7 @@ sub print_pdf_start_combobox { my $result; my ($fieldName) = @_; $result .= '\begin{tabularx}{\textwidth}{p{2.5cm}X}'."\n"; - $result .= '\comboBox[]{'.$fieldName.'}{2.3cm}{14bp}{'; # + $result .= '\comboBox[]{'.$fieldName.'}{2.3cm}{14bp}{'; # return $result; } @@ -2217,10 +2543,10 @@ $option: PDF internal name of the Combob sub print_pdf_add_combobox_option { my $result; - my ($option) = @_; + my ($option) = @_; $result .= '('.$option.')'; - + return $result; }