# The LearningOnline Network with CAPA # # $Id: lonhelp.pm,v 1.47 2022/05/27 05:09:21 raeburn Exp $ # # .tex help system web server handler # # Copyright Michigan State University Board of Trustees # # This file is part of the LearningOnline Network with CAPA (LON-CAPA). # # LON-CAPA is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # LON-CAPA is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with LON-CAPA; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # /home/httpd/html/adm/gpl.txt # # http://www.lon-capa.org/ # # .tex file help handler package Apache::lonhelp; use strict; use Apache::Constants qw(:common :http); use Apache::File(); use Apache::loncommon(); use Apache::lonacc(); use Apache::lontexconvert(); use Apache::lonnavmaps; # for advancedUser use Apache::lonlocal; use Apache::lonnet; use tth(); use GDBM_File(); use lib '/home/httpd/lib/perl/'; use LONCAPA; # This sub takes the name of a label in, and converts it to something # that is a valid anchor name. sub processLabelName { my ($name) = @_; $name =~ tr/a-zA-Z0-9/_/cs; return $name; } # Serve out the text sub servetext { my ($r,$uri,$text,$is_mobile,$firstfile) = @_; my $bugs; my %helpconfig = &Apache::lonnet::get_dom('configuration',['helpsettings'], $env{'request.role.domain'}); if (ref($helpconfig{'helpsettings'}) eq 'HASH') { if ($helpconfig{'helpsettings'}{'submitbugs'} eq '1') { $bugs = &Apache::loncommon::help_open_bug('Documentation',&mt('Report a documentation bug')); } } my %lt = &Apache::lonlocal::texthash( header => 'LON-CAPA Help', search => 'Search LON-CAPA help', query => 'Search', ); my $goback; if ((($env{'request.lti.login'}) && ($env{'request.lti.target'} eq 'iframe')) || (($env{'request.deeplink.login'}) && ($env{'request.deeplink.target'} eq '_self'))) { $goback = ''. ''.&mt('Go Back').''. ' '; } $r->print(<help logo$goback$lt{'header'}
HEADER if ($is_mobile) { my $width = 500; my $height = 400; my $machine = &Apache::lonnet::absolute_url(); $r->print(&Apache::loncommon::nicescroll_javascript('helpwrapper', {cursorcolor => '#00F', railalign => 'right', railoffset => '{top:5,left:40}'}, undef,1,$machine.$firstfile)); $r->print('
'. $text. '
'); } else { $r->print($text); } if (&Apache::lonnavmaps::advancedUser()) { $r->print(<
$lt{'search'}
$bugs FOOTER } $r->print(< ENDBODY } # Render takes a tex fragment, transforms it for TtH, and returns the # HTML equivalent sub render { my ($tex, $docroot) = @_; tie (my %fragmentLabels, 'GDBM_File', $docroot . '/adm/help/fragmentLabels.gdbm', 0, 0); # This tells TtH what to do with captions, labels, and other # things $tex = "\\documentclass{article}\n" . $tex; # We process these ourselves because TtH can't handle then without # LaTeX .aux files # absolute paths for use with help.loncapa.org $tex =~ s| \\ref\{([^}]*)\} | my $label=$1; my $icon='/adm/help/help.png'; my $ext; if ($1!~/\.hlp$/) { if (($1 =~ /^\w+\.manual\.pdf$/) && (-e $docroot.'/adm/help/'.$1)) { $icon = '/adm/lonIcons/pdf.gif'; } elsif ((!exists($fragmentLabels{$1})) && ($1!~/\.hlp$/)) { &Apache::lonnet::logthis("ERROR: $1 not a valid help label"); $label='Error'; } else { $label=substr($fragmentLabels{$1}, 0, -4); $ext = '.hlp#' . &processLabelName($1); } } else { $label=~s/\.hlp$//; $ext = '.hlp#' . &processLabelName($1); } '\\begin{html}'.&mt('Help').'' . '\\end{html}' |gxe; # Backslashes $tex =~ s|\\textbackslash|###BACKSLASH###|g; # Figures leftover without captions $tex =~ s| \\includegraphics(\[[^]]*\])*\{([^}]*)\} | '\\begin{html}\\end{html}' |gxe; $tex=&Apache::lontexconvert::tth_converted(\$tex); # Finish backslashes $tex =~ s/###BACKSLASH###/'\\'/ge; # Fix the pretty quotes $tex =~ s/('')|(``)/"/g; #" to get emacs syntax highlighter happy $tex =~ s/`/'/g; # For some reason all captions come out as "Figure 0:", so # just duck the issue... $tex =~ s/Figure 0://g; $tex.=$Apache::lontexconvert::errorstring; untie %fragmentLabels; return $tex; } sub listmatches { my ($docroot,$term,$subdir) =@_; unless ($subdir) { $subdir=''; } my $output=''; opendir(DIR,$docroot.'/adm/help/tex/'.$subdir); foreach my $filename (sort readdir(DIR)) { if ($filename=~/\.tex$/) { open(FH,$docroot.'/adm/help/tex/'.$subdir.$filename); my $quote=''; while (my $line=) { if ($line=~/\Q$term\E/i) { $line=~s/\\\w+//gs; $line=~s/\{//gs; $line=~s/\}//gs; $line=~s/\\/ /gs; $line=~s/\/\>\;/gs; $line=~s/(\Q$term\E)/\$1\<\/b\>/gsi; $quote.='
...'.$line.'...'; } } close(FH); if ($quote) { my $title=$filename; $title=~s/\_/ /gs; $title=~s/\.tex$//; $filename=~s/\.tex$/\.hlp/; $output.='
  • '.$title.''.$quote.'
  • '; } } } closedir(DIR); return (($output?'
      '.$output.'
    ':&mt('"[_1]" not found',$term)),$output); } sub handler { my $r = shift; my $docroot = $r->dir_config('lonDocRoot'); &Apache::lonlocal::get_language_handle($r); &Apache::loncommon::content_type($r,"text/html"); my $caller; if ($env{'form.searchterm'}=~/\w/) { $caller = 'search'; } my $starthash; if ($env{'browser.mobile'}) { $starthash = { only_body => 1, add_entries => { 'onload' => "javascript:expand_div('$caller');", }, }; } else { $starthash = { only_body => 1, }; } my $firstfile; my $start_page= &Apache::loncommon::start_page('LON-CAPA Help',undef,$starthash); my $text=''; my $uri = $r->uri; if ($env{'form.searchterm'}=~/\w/) { ($text,my $matches)=&listmatches($docroot,$env{'form.searchterm'},&Apache::lonlocal::current_language().'/'); if ($matches) { my ($englishresult,$englishmatches)=&listmatches($docroot,$env{'form.searchterm'}); if ($englishmatches) { $text.='
    '.$englishresult; } } else { $text=&listmatches($docroot,$env{'form.searchterm'}); } } else { my $filenames = &unescape(substr($uri,rindex($uri,'/')+1,-4)); # Security check on the file; the whole filename must consist # of nothing but alphanums, ' ,, or ., or the file # will be "not found", no matter what. return HTTP_NOT_FOUND if ($filenames !~ /\A[-0-9a-zA-z_'',:.]+\Z/); # Join together the tex files, return HTTP_NOT_FOUND if any of # them are not found my $tex = ''; # Since in insertlist.tab I want to specify multiple files, # and insertlist.tab also uses commas, I need something else # so replace : with , $filenames =~ s/:/,/g; my @files = split(/,/, $filenames); $firstfile = '/adm/help/'.$files[0].'.hlp'; my $count = 0; for my $filename (@files) { if (-e $docroot.'/adm/help/tex/'. &Apache::lonlocal::current_language().'/'. $filename.'.tex') { $filename=&Apache::lonlocal::current_language().'/'.$filename; } (my $file = Apache::File->new($docroot . '/adm/help/tex/'.$filename.'.tex')) or return HTTP_NOT_FOUND; $tex .= join('', <$file>); $count ++; if (scalar(@files) > $count) { $tex .= '\hrulefill'; } } $text = &render($tex, $docroot); } $r->send_http_header; $r->print($start_page); &servetext($r,$uri,$text,$env{'browser.mobile'},$firstfile); $r->print(&Apache::loncommon::end_page()); return OK; } 1;