#!/usr/bin/perl # # Copyright (C) Koji Nakamaru # # Author: Koji Nakamaru (nakamaru at gmail.com) # Modified: Apr 30 2005 # * changed the contact information. # Created/Modified: Jan 2 2005 # Keywords: tex, latex, math, web # # This program 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, or (at your option) # any later version. # # This program 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 GNU Emacs; see the file COPYING. If not, write to the # Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # use strict; use File::Temp qw/ mkdtemp /; use FCGI; my $cache_size_limit = 5 * 1024 * 1024; sub xerror; sub getContents; sub cacheCheck; sub cacheAdd; my $pngerr = &getContents("preverr.png"); if (! defined($pngerr)) { die "wrong installation or file system error\n"; } my %cache; my %cache_hit; my $cache_size = 0; my $tmpdir; my $fcgi = FCGI::Request(); while ($fcgi->FCGI::Accept() >= 0) { my $req = $ENV{'QUERY_STRING'}; my $png = &cacheCheck($req); if (! defined($png)) { my $res = 96; my $cmd = $req; # $cmd =~ tr/+/ /; $cmd =~ s/%([a-fA-F0-9]{2})/pack("C",hex($1))/eg; if ($cmd =~ /^\s*\[([^]]+)\](.+)\s*$/) { $cmd = $2; my $opt = $1; $opt =~ s/\s+//g; if ($opt =~ /res=(\d+)/) { $res = $1; } else { &xerror("found unknown option: $1."); next; } } if (! ($res =~ /\d+/ && 10 <= $res && $res <= 1200)) { &xerror("found res out of range [10,1000]."); next; } if ($cmd eq '') { &xerror("found no string."); next; } $tmpdir = mkdtemp("imgtexwork/tXXXXXX"); if (! open(FO, "> $tmpdir/t.tex")) { &xerror("failed to generate a tex file."); next; } print FO <<"EOF"; \\documentclass\{article\} \\usepackage\{type1cm\} \\usepackage[psamsfonts]\{amssymb\} \\usepackage\{amsmath\} \\begin\{document\} \\thispagestyle{empty} $cmd \\end\{document\} EOF close FO; if (system("ulimit -t 10 -f 1024 -c 0; cd $tmpdir ; latex '\\nonstopmode\\input' t.tex > /dev/null 2>&1 ; case \$? in 0) dvipng -q -D $res -T tight -M -pp 1 -bg Transparent --truecolor --noghostscript t.dvi -o t%03d.png > /dev/null 2>&1 ;; *) exit 1 ;; esac") != 0) { &xerror("failed to generate a dvi file."); next; } $png = &getContents("$tmpdir/t001.png"); } if (defined($png)) { &cacheAdd($req, $png); print "Content-type: image/png\r\n\r\n", $png; } else { &xerror("failed to generate a png file."); } system("rm -rf $tmpdir"); } sub xerror { my ($msg) = @_; print "Content-type: image/png\r\n\r\n", $pngerr; system("rm -rf $tmpdir"); } sub getContents { my ($fname) = @_; my $contents = undef; open FI, "< $fname" or return $contents; { local $/; $contents = ; } close FI; return $contents; } sub cacheCheck { my ($req) = @_; if (defined($cache{$req})) { $cache_hit{$req} = localtime(); return $cache{$req}; } return undef; } sub cacheAdd { my ($req, $png) = @_; $cache{$req} = $png; $cache_hit{$req} = localtime(); $cache_size += length($png); my $now = localtime(); while ($cache_size > $cache_size_limit) { my $key0 = undef; my $hit0 = $now; foreach my $key (keys(%cache_hit)) { my $hit = $cache_hit{$key}; if ($hit < $hit0) { $key0 = $key; $hit0 = $hit; } } if (defined($key0)) { $cache_size -= length($cache{$key0}); $cache{$key0} = undef; $cache_hit{$key0} = undef; } } }