--- loncom/interface/lonprintout.pm 2008/01/14 10:43:12 1.511 +++ loncom/interface/lonprintout.pm 2008/03/24 00:03:05 1.519.2.2 @@ -1,8 +1,7 @@ -# # The LearningOnline Network # Printout # -# $Id: lonprintout.pm,v 1.511 2008/01/14 10:43:12 foxr Exp $ +# $Id: lonprintout.pm,v 1.519.2.2 2008/03/24 00:03:05 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -39,6 +38,8 @@ use Apache::edit; use Apache::File(); use Apache::lonnavmaps; use Apache::admannotations; +use Apache::lonenc; +use HTTP::Response; use LONCAPA::map(); use POSIX qw(strftime); @@ -50,6 +51,21 @@ my %perm; my %parmhash; my $resources_printed; +# Global variables that describe errors in ssi calls detected by ssi_with_retries. +# + +my $ssi_error; # True if there was an ssi error. +my $ssi_last_error_resource; # The resource URI that could not be fetched. +my $ssi_last_error; # The error text from the server. (e.g. 500 Server timed out). + +# +# Our ssi max retry count. +# + +my $ssi_retry_count = 5; # Some arbitrary value. + + + # Fetch the contents of a resource, uninterpreted. # This is used here to fetch a latex file to be included # verbatim into the printout< @@ -93,6 +109,55 @@ sub annotate { return $result; } + +# +# ssi_with_retries - Does the server side include of a resource. +# if the ssi call returns an error we'll retry it up to +# the number of times requested by the caller. +# If we still have a proble, no text is appended to the +# output and we set some global variables. +# to indicate to the caller an SSI error occured. +# All of this is supposed to deal with the issues described +# in LonCAPA BZ 5631 see: +# http://bugs.lon-capa.org/show_bug.cgi?id=5631 +# by informing the user that this happened. +# +# Parameters: +# resource - The resource to include. This is passed directly, without +# interpretation to lonnet::ssi. +# form - The form hash parameters that guide the interpretation of the resource +# +# retries - Number of retries allowed before giving up completely. +# Returns: +# On success, returns the rendered resource identified by the resource parameter. +# Side Effects: +# The following global variables can be set: +# ssi_error - If an unrecoverable error occured this becomes true. +# It is up to the caller to initialize this to false +# if desired. +# ssi_last_error_resource - If an unrecoverable error occured, this is the value +# of the resource that could not be rendered by the ssi +# call. +# ssi_last_error - The error string fetched from the ssi response +# in the event of an error. +# +sub ssi_with_retries { + my ($resource, $retries, %form) = @_; + + + my ($content, $response) = &Apache::loncommon::ssi_with_retries($resource, $retries, %form); + if (!$response->is_success) { + $ssi_error = 1; + $ssi_last_error_resource = $resource; + $ssi_last_error = $response->code . " " . $response->message; + + &Apache::lonnet::logthis("Error in SSI resource: $resource Error: $ssi_last_error"); + } + + return $content; + +} + # # printf_style_subst item format_string repl # @@ -743,6 +808,7 @@ sub character_chart { $result =~ s/&(hearts|\#9829);/\\ensuremath\{\\heartsuit\}/g; $result =~ s/&(diams|\#9830);/\\ensuremath\{\\diamondsuit\}/g; # Chemically useful 'things' contributed by Hon Kie (bug 4652). + $result =~ s/&\#8636;/\\ensuremath\{\\leftharpoonup\}/g; $result =~ s/&\#8637;/\\ensuremath\{\\leftharpoondown\}/g; $result =~ s/&\#8640;/\\ensuremath\{\\rightharpoonup\}/g; @@ -756,6 +822,13 @@ sub character_chart { $result =~ s/&\#8600;/\\ensuremath\{\\searrow\}/g; $result =~ s/&\#8601;/\\ensuremath\{\\swarrow\}/g; $result =~ s/&\#8598;/\\ensuremath\{\\nwarrow\}/g; + + # Left/right quotations: + + $result =~ s/&(ldquo|#8220);/\`\`/g; + $result =~ s/&(rdquo|#8221);/\'\'/g; + + return $result; } @@ -775,7 +848,7 @@ my %page_formats= 'legal' => { 'book' => { '1' => ['7.1 in','13 in',,'-0.57 in','-0.57 in','-0.5 in'], - '2' => ['3.16 in','13 in','-0.57 in','-0.57 in','-0.5 in'] + '2' => ['3.66 in','13 in','-0.57 in','-0.57 in','-0.5 in'] }, 'album' => { '1' => ['12 in','7.1 in',,'-0.57 in','-0.57 in','-0.5 in'], @@ -1054,6 +1127,7 @@ sub print_latex_header { '\usepackage[dvips]{graphicx}\usepackage{epsfig}'."\n". '\usepackage{wrapfig}'. '\usepackage{picins}\usepackage{calc}'."\n". + '\usepackage[utf8]{inputenc}'."\n". '\newenvironment{choicelist}{\begin{list}{}{\setlength{\rightmargin}{0in}'."\n". '\setlength{\leftmargin}{0.13in}\setlength{\topsep}{0.05in}'."\n". '\setlength{\itemsep}{0.022in}\setlength{\parsep}{0in}'."\n". @@ -1245,7 +1319,7 @@ sub print_construction_sequence { $form{'latex_type'}=$helper->{'VARS'}->{'LATEX_TYPE'}; $form{'rndseed'}=$rndseed; $resources_printed .=$urlp.':'; - $texversion=&Apache::lonnet::ssi($urlp,%form); + $texversion=&ssi_with_retries($urlp, $ssi_retry_count, %form); } if((($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') || ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'only')) && @@ -1258,7 +1332,7 @@ sub print_construction_sequence { $answerform{'problem_split'}=$parmhash{'problem_stream_switch'}; if ($urlp=~/\/res\//) {$env{'request.state'}='published';} $resources_printed .= $urlp.':'; - my $answer=&Apache::lonnet::ssi($urlp,%answerform); + my $answer=&ssi_with_retries($urlp, $ssi_retry_count, %answerform); if ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') { $texversion=~s/(\\keephidden{ENDOFPROBLEM})/$answer$1/; } else { @@ -1313,6 +1387,7 @@ sub print_construction_sequence { sub output_data { my ($r,$helper,$rparmhash) = @_; my %parmhash = %$rparmhash; + $ssi_error = 0; # This will be set nonzero by failing ssi's. $resources_printed = ''; my $do_postprocessing = 1; my $js = < ENDPART + + my $start_page = &Apache::loncommon::start_page('Preparing Printout',$js); my $msg = &mt('Please stand by while processing your print request, this may take some time ...'); @@ -1375,6 +1452,7 @@ ENDPART my @print_array=(); my @student_names=(); + # Common settings for the %form has: # In some cases these settings get overriddent by specific cases, but the # settings are common enough to make it worthwhile factoring them out @@ -1412,6 +1490,7 @@ ENDPART $currentURL=$helper->{'VARS'}->{'postdata'}; $cleanURL=&Apache::lonenc::check_decrypt($currentURL); } else { + #prints resource from the construction space $currentURL='/'.$helper->{'VARS'}->{'filename'}; if ($currentURL=~/([^?]+)/) {$currentURL=$1;} @@ -1444,7 +1523,7 @@ ENDPART &Apache::lonxml::clear_problem_counter(); $resources_printed .= $currentURL.':'; - $texversion.=&Apache::lonnet::ssi($currentURL,%form); + $texversion.=&ssi_with_retries($currentURL,$ssi_retry_count, %form); # Add annotations if required: @@ -1465,7 +1544,7 @@ ENDPART $form{'problemtype'}='exam'; } $resources_printed .= $currentURL.':'; - my $answer=&Apache::lonnet::ssi($currentURL,%form); + my $answer=&ssi_with_retries($currentURL,$ssi_retry_count, %form); if ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') { @@ -1526,7 +1605,7 @@ ENDPART $form{'latex_type'}=$helper->{'VARS'}->{'LATEX_TYPE'}; if ($currentURL=~/\/syllabus$/) {$currentURL=~s/\/res//;} $resources_printed .= $currentURL.':'; - my $texversion=&Apache::lonnet::ssi($currentURL,%form); + my $texversion=&ssi_with_retries($currentURL, $ssi_retry_count, %form); if ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes') { my $annotation = &annotate($currentURL); $texversion =~ s/(\\end{document})/$annotation$1/; @@ -1587,6 +1666,8 @@ ENDPART my $pbreakresources = keys %page_breaks; for (my $i=0;$i<=$#master_seq;$i++) { + &Apache::lonenc::reset_enc(); + # Note due to document structure, not allowed to put \newpage # prior to the first resource @@ -1595,11 +1676,12 @@ ENDPART $result.="\\newpage\n"; } } - my ($sequence,undef,$urlp)=&Apache::lonnet::decode_symb($master_seq[$i]); + my ($sequence,$middle_thingy,$urlp)=&Apache::lonnet::decode_symb($master_seq[$i]); $urlp=&Apache::lonnet::clutter($urlp); $form{'symb'}=$master_seq[$i]; my $assignment=&Apache::lonxml::latex_special_symbols(&Apache::lonnet::gettitle($sequence),'header'); #title of the assignment which contains this problem + if ($selectionmade==7) {$helper->{VARS}->{'assignment'}=$assignment;} if ($i==0) {$prevassignment=$assignment;} my $texversion=''; @@ -1607,7 +1689,7 @@ ENDPART && $urlp=~/\.(problem|exam|quiz|assess|survey|form|library|page|xml|html|htm|xhtml|xhtm)$/) { $resources_printed .= $urlp.':'; &Apache::lonxml::remember_problem_counter(); - $texversion.=&Apache::lonnet::ssi($urlp,%form); + $texversion.=&ssi_with_retries($urlp, $ssi_retry_count, %form); if ($urlp=~/\.page$/) { ($texversion,my $number_of_columns_page) = &page_cleanup($texversion); if ($number_of_columns_page > $number_of_columns) {$number_of_columns=$number_of_columns_page;} @@ -1624,7 +1706,7 @@ ENDPART $resources_printed .= $urlp.':'; &Apache::lonxml::restore_problem_counter(); - my $answer=&Apache::lonnet::ssi($urlp,%answerform); + my $answer=&ssi_with_retries($urlp, $ssi_retry_count, %answerform); if ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') { $texversion=~s/(\\keephidden{ENDOFPROBLEM})/$answer$1/; @@ -1679,7 +1761,7 @@ ENDPART $form{'latex_type'}=$helper->{'VARS'}->{'LATEX_TYPE'}; if ($urlp=~/\/syllabus$/) {$urlp=~s/\/res//;} $resources_printed .= $urlp.':'; - my $texversion=&Apache::lonnet::ssi($urlp,%form); + my $texversion=&ssi_with_retries($urlp, $ssi_retry_count, %form); if ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes') { my $annotation = &annotate($urlp); $texversion =~ s/(\\end{document)/$annotation$1/; @@ -1906,6 +1988,9 @@ ENDPART $rndseed=$helper->{'VARS'}->{'curseed'}; } for (my $i=0;$i<=$#list_of_files;$i++) { + + &Apache::lonenc::reset_enc(); + my $urlp = $list_of_files[$i]; $urlp=~s|//|/|; if ($urlp=~/\//) { @@ -1917,7 +2002,7 @@ ENDPART $urlp =~ s|^$Apache::lonnet::perlvar{'lonDocRoot'}||; } $resources_printed .= $urlp.':'; - my $texversion=&Apache::lonnet::ssi($urlp,%form); + my $texversion=&ssi_with_retries($urlp, $ssi_retry_count, %form); if(($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') || ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'only')) { # Don't permanently pervert %form: @@ -1927,7 +2012,7 @@ ENDPART $answerform{'latex_type'}=$helper->{'VARS'}->{'LATEX_TYPE'}; $answerform{'rndseed'}=$rndseed; $resources_printed .= $urlp.':'; - my $answer=&Apache::lonnet::ssi($urlp,%answerform); + my $answer=&ssi_with_retries($urlp, $ssi_retry_count, %answerform); if ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') { $texversion=~s/(\\keephidden{ENDOFPROBLEM})/$answer$1/; } else { @@ -1944,7 +2029,8 @@ ENDPART $texversion.='\vskip 1 mm '.$answer.'\end{document}'; } } - #this chunck is responsible for printing the path to problem + #this chunk is responsible for printing the path to problem + my $newurlp=$urlp; if ($newurlp=~/~/) {$newurlp=~s|\/~([^\/]+)\/|\/home\/$1\/public_html\/|;} $newurlp=&path_to_problem($newurlp,$LaTeXwidth); @@ -1984,62 +2070,9 @@ ENDPART #} } -#-- writing .tex file in prtspool - my $temp_file; - my $identifier = &Apache::loncommon::get_cgi_id(); - my $filename = "/home/httpd/prtspool/$env{'user.name'}_$env{'user.domain'}_printout_$identifier.tex"; - if (!($#print_array>0)) { - unless ($temp_file = Apache::File->new('>'.$filename)) { - $r->log_error("Couldn't open $filename for output $!"); - return SERVER_ERROR; - } - print $temp_file $result; - my $begin=index($result,'\begin{document}',0); - my $inc=substr($result,0,$begin+16); - } else { - my $begin=index($result,'\begin{document}',0); - my $inc=substr($result,0,$begin+16); - for (my $i=0;$i<=$#print_array;$i++) { - if ($i==0) { - $print_array[$i]=$result; - } else { - $print_array[$i].='\end{document}'; - $print_array[$i] = - &latex_corrections($number_of_columns,$print_array[$i], - $selectionmade, - $helper->{'VARS'}->{'ANSWER_TYPE'}); - - my $anobegin=index($print_array[$i],'\setcounter{page}',0); - substr($print_array[$i],0,$anobegin)=''; - $print_array[$i]=$inc.$print_array[$i]; - } - my $temp_file; - my $newfilename=$filename; - my $num=$i+1; - $newfilename =~s/\.tex$//; - $newfilename=sprintf("%s_%03d.tex",$newfilename, $num); - unless ($temp_file = Apache::File->new('>'.$newfilename)) { - $r->log_error("Couldn't open $newfilename for output $!"); - return SERVER_ERROR; - } - print $temp_file $print_array[$i]; - } - } - my $student_names=''; - if ($#print_array>0) { - for (my $i=0;$i<=$#print_array;$i++) { - $student_names.=$student_names[$i].'_ENDPERSON_'; - } - } else { - if ($#student_names>-1) { - $student_names=$student_names[0].'_ENDPERSON_'; - } else { - my $fullname = &get_name($env{'user.name'},$env{'user.domain'}); - $student_names=join(':',$env{'user.name'},$env{'user.domain'}, - $env{'request.course.sec'},$fullname). - '_ENDPERSON_'.'_END_'; - } - } + # Set URLback if this is a construction space print so we can provide + # a link to the resource being edited. + # my $URLback=''; #link to original document if ($helper->{'VARS'}->{'construction'} eq '1') { @@ -2050,34 +2083,121 @@ ENDPART $URLback=~s|^/~|/priv/|; } } - # logic for now is too complex to trace if this has been defined - # yet. - my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; - my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; - &Apache::lonnet::appenv('cgi.'.$identifier.'.file' => $filename, - 'cgi.'.$identifier.'.layout' => $laystyle, - 'cgi.'.$identifier.'.numcol' => $numberofcolumns, - 'cgi.'.$identifier.'.paper' => $papersize, - 'cgi.'.$identifier.'.selection' => $selectionmade, - 'cgi.'.$identifier.'.tableofcontents' => $helper->{'VARS'}->{'TABLE_CONTENTS'}, - 'cgi.'.$identifier.'.tableofindex' => $helper->{'VARS'}->{'TABLE_INDEX'}, - 'cgi.'.$identifier.'.role' => $perm{'pav'}, - 'cgi.'.$identifier.'.numberoffiles' => $#print_array, - 'cgi.'.$identifier.'.studentnames' => $student_names, - 'cgi.'.$identifier.'.backref' => $URLback,); - &Apache::lonnet::appenv("cgi.$identifier.user" => $env{'user.name'}, - "cgi.$identifier.domain" => $env{'user.domain'}, - "cgi.$identifier.courseid" => $cnum, - "cgi.$identifier.coursedom" => $cdom, - "cgi.$identifier.resources" => $resources_printed); - my $end_page = &Apache::loncommon::end_page(); - $r->print(<print(' +
+

'.&mt('An unrecoverable error occured:').'

+

+ '.&mt('One of the resources ([_1]) you chose to print could not be rendered due to an unrecoverable error when communicating with a server:',$ssi_last_error_resource).' +
+'.$ssi_last_error.' +

+

'. +&mt('It is recommended that you try printing again later, as this error may mean the server was just temporarily unavailable, or is down for maintenance.').'
'. +&mt('If the error persists, please contact the [_1] for assistance.',$helpurl). +'

'. +&mt('We apologize for the inconvenience.'). +'

'. +$end_page); + + } else { + +#-- writing .tex file in prtspool + my $temp_file; + my $identifier = &Apache::loncommon::get_cgi_id(); + my $filename = "/home/httpd/prtspool/$env{'user.name'}_$env{'user.domain'}_printout_$identifier.tex"; + if (!($#print_array>0)) { + unless ($temp_file = Apache::File->new('>'.$filename)) { + $r->log_error("Couldn't open $filename for output $!"); + return SERVER_ERROR; + } + print $temp_file $result; + my $begin=index($result,'\begin{document}',0); + my $inc=substr($result,0,$begin+16); + } else { + my $begin=index($result,'\begin{document}',0); + my $inc=substr($result,0,$begin+16); + for (my $i=0;$i<=$#print_array;$i++) { + if ($i==0) { + $print_array[$i]=$result; + } else { + $print_array[$i].='\end{document}'; + $print_array[$i] = + &latex_corrections($number_of_columns,$print_array[$i], + $selectionmade, + $helper->{'VARS'}->{'ANSWER_TYPE'}); + + my $anobegin=index($print_array[$i],'\setcounter{page}',0); + substr($print_array[$i],0,$anobegin)=''; + $print_array[$i]=$inc.$print_array[$i]; + } + my $temp_file; + my $newfilename=$filename; + my $num=$i+1; + $newfilename =~s/\.tex$//; + $newfilename=sprintf("%s_%03d.tex",$newfilename, $num); + unless ($temp_file = Apache::File->new('>'.$newfilename)) { + $r->log_error("Couldn't open $newfilename for output $!"); + return SERVER_ERROR; + } + print $temp_file $print_array[$i]; + } + + } + my $student_names=''; + if ($#print_array>0) { + for (my $i=0;$i<=$#print_array;$i++) { + $student_names.=$student_names[$i].'_ENDPERSON_'; + } + } else { + if ($#student_names>-1) { + $student_names=$student_names[0].'_ENDPERSON_'; + } else { + my $fullname = &get_name($env{'user.name'},$env{'user.domain'}); + $student_names=join(':',$env{'user.name'},$env{'user.domain'}, + $env{'request.course.sec'},$fullname). + '_ENDPERSON_'.'_END_'; + } + } + + # logic for now is too complex to trace if this has been defined + # yet. + my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + &Apache::lonnet::appenv('cgi.'.$identifier.'.file' => $filename, + 'cgi.'.$identifier.'.layout' => $laystyle, + 'cgi.'.$identifier.'.numcol' => $numberofcolumns, + 'cgi.'.$identifier.'.paper' => $papersize, + 'cgi.'.$identifier.'.selection' => $selectionmade, + 'cgi.'.$identifier.'.tableofcontents' => $helper->{'VARS'}->{'TABLE_CONTENTS'}, + 'cgi.'.$identifier.'.tableofindex' => $helper->{'VARS'}->{'TABLE_INDEX'}, + 'cgi.'.$identifier.'.role' => $perm{'pav'}, + 'cgi.'.$identifier.'.numberoffiles' => $#print_array, + 'cgi.'.$identifier.'.studentnames' => $student_names, + 'cgi.'.$identifier.'.backref' => $URLback,); + &Apache::lonnet::appenv("cgi.$identifier.user" => $env{'user.name'}, + "cgi.$identifier.domain" => $env{'user.domain'}, + "cgi.$identifier.courseid" => $cnum, + "cgi.$identifier.coursedom" => $cdom, + "cgi.$identifier.resources" => $resources_printed); + + my $end_page = &Apache::loncommon::end_page(); + $r->print(< Continue $end_page FINALEND + } # endif ssi errors. } @@ -2275,6 +2395,8 @@ sub handler { if(-e $conversion_queuefile) { unlink $conversion_queuefile; } + + &output_data($r,$helper,\%parmhash); return OK; } @@ -2369,6 +2491,10 @@ sub printHelper { $helper->declareVar("showallfoils"); $helper->declareVar("STUDENTS"); + + + + # The page breaks can get loaded initially from the course environment: # But we only do this in the initial state so that they are allowed to change. # @@ -2462,7 +2588,7 @@ sub printHelper { $helper->{VARS}->{'curseed'}=$env{'form.curseed'}; } if (!$helper->{VARS}->{'probstatus'} && $env{'form.problemtype'}) { - $helper->{VARS}->{'probstatus'}=$env{'form.problemtype'}; + $helper->{VARS}->{'probstatus'}=$env{'form.problemstatus'}; } my $userCanSeeHidden = Apache::lonnavmaps::advancedUser(); @@ -3088,6 +3214,29 @@ CHOOSE_FROM_ANY_SEQUENCE RNDSEED &Apache::lonxml::xmlparse($r, 'helper', $xmlfrag); + + + addMessage("Problem Type:"); + # + # Initial value from construction space: + # + if (!$helper->{VARS}->{'probstatus'} && $env{'form.problemtype'}) { + $helper->{VARS}->{'probstatus'} = $env{'form.problemtype'}; # initial value + } + $xmlfrag = << "PROBTYPE"; + + + return "$helper->{VARS}->{'probstatus'}"; + + Homework Problem + Exam Problem + Survey question + +PROBTYPE + &Apache::lonxml::xmlparse($r, 'helper', $xmlfrag); + + addMessage(""); + } }