#!/usr/bin/perl -Tw #----------------------------------------------------------------------------- # cdinsert.pl # # Web interface to "cdlabelgen" # Creates CD Jewel Case Inserts, files output in PostScript and PDF formats. # This script is similar to the script used for the Online Interface at: # http://www.aczoom.com/tools/cdinsert/ # and is provided as an example. There is no documention for this script, # other than program comments in this file itself. # See the "INSTALL.WEB" file for HTML fragments of files used by the # script (wait_t, done_t, and the main form itself), and crontab entries. # ----------------------------------------------------------------------- my $VERSION = "1.53"; # Last Modified: October 21, 2004 # Changed aczone to aczoom # Updates by Avinash Chopde http://www.aczoom.com/ # ----------------------------------------------------------------------- # Created: March 2001, by Avinash Chopde www.aczoom.com # ----------------------------------------------------------------------- # Copyright (C) 2002 Avinash Chopde http://www.aczoom.com/ # # All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, and/or sell copies of the Software, and to permit persons # to whom the Software is furnished to do so, provided that the above # copyright notice(s) and this permission notice appear in all copies of # the Software and that both the above copyright notice(s) and this # permission notice appear in supporting documentation. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT # OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR # HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL # INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING # FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # # Except as contained in this notice, the name of a copyright holder # shall not be used in advertising or otherwise to promote the sale, use # or other dealings in this Software without prior written authorization # of the copyright holder. # ======================================================================== # March 2001, Avinash Chopde http://www.aczoom.com/ #------------------------------ # Rough outline of things needed to make this work at your site: # Programs needed, on Linux: netpbm, # GhostScript - use version 5.10 - it is twice as fast as version 6.5 # cdlabelgen - install (default goes in /usr/local/bin and /usr/local/lib) # netpbm - using version 9.22 (Dec 2001) # jpeg2ps - using version 1.8, from http://www.pdflib.com/jpeg2ps/ # CGI.pm - latest one - 2.752 or newer # ---- # Make this folder non-writeable: # $ROOTDIR # Safest is to make all files and directories non-writeable, # and all directories below $ROOTDIR should be additionally non-readable # by group and others (ROOTDIR itself needs to be readable, Apache reads # it to find index.html, index.shtml, etc). # commands: chmod -R a-w $ROOTDIR; chmod go-r # # Files/folders in $ROOTDIR: # cdinsert.html [entry point, INSTALL.WEB has examples] # wait_t.html # done_t.html # cdinsert.pl (copy to http:/cgi-bin) # Files/folders in any PATH dir: # cdlabelgen # ---- # $WORKDIR --> Make the PARENT of this folder writeable by everybody # (but not readable). This is where the temp files are created. # --- # $LOGFILE - make this chmod 662 - writeable, but not readable by others # so casual web hackers can't read this directly using a browser. # But if the file has to be owned by nobody.nobody (for web server), # then make it chmod 226 instead # --- # Finally, edit the top section of this CGI script to point to files at # your site. # To test, run with the -t option, using the example webtest.txt or similar # files: # cdinsert.pl -t /tmp/webtest.txt # -t should use full path for filename. #----------------------------------------------------------------------------- use 5.005; # perl newer than 5.005 required use CGI 2.50 qw(escapeHTML); # 2.47 for upload, 2.50 for Vars use Getopt::Std; use POSIX qw(floor); use File::Copy; use Socket qw(:DEFAULT :crlf); #----------------------------------------------------------------------------- $start_time = time(); $SIG{HUP} = $SIG{INT} = $SIG{QUIT} = $SIG{PIPE} = $SIG{TERM} = \&sighandler; #----------------------------------------------------------------------------- # Following vars need to be set specifically for each site $ROOTDIR = "/home/cgi/cdinsert"; # where all web files are kept # "/usr/local/apache/htdocs/cgi" is symlink to "/home/cgi", so # the HTTP address is: # $ROOTHTTP = "/cgi/cdinsert"; # relative URL, absolute path # for each invocation - semi-random name - gets some privacy, since # these folders are readable by the world. # $WORKDIRNAME = "cd" . floor(rand(100)) . "$$"; # keep it max 4 chars + $$ # $TDATE = sprintf("%02d%02d%02d", (localtime($start_time))[3], (localtime($start_time))[2], (localtime($start_time))[1]); # current date hour minute $TDATE = sprintf("%02d%02d", (localtime($start_time))[3], (localtime($start_time))[2]); # current date hour $WORKDIRNAME = "cd" . $TDATE; $WORKDIRNAME = &mktempdir("/home/cgi/tmp", $WORKDIRNAME, floor(rand(1e3))); # 1e3 -> max 3 digits $WORKDIR = "/home/cgi/tmp/$WORKDIRNAME"; # "/usr/local/apache/htdocs/cgi" is symlink to "/home/cgi", so $WORKHTTP = "/cgi/tmp/$WORKDIRNAME"; $LOGFILE = "/home/cgi/tmp/weblog.txt"; # log file - global script issues, not related to any one invocation # make sure this file exists, and is chmod 662 - writeable, but not readable # by others so casual web hackers can't read this directly using a browser. # for each invocation - semi-random name for files - gets some privacy, since # these folders and files are readable by the world. $WORKID = floor(rand(1e4)); $WORKFILE = "cd" . $WORKID; # 'cd' followed by upto 4 digits $MSGFILENAME = "log$WORKID.txt"; $MSGFILE = "$WORKDIR/$MSGFILENAME"; # STDOUT/STDERR messages collected here, different file for each invocation $WEBWAIT_THTML = "$ROOTDIR/wait_t.html"; # partial HTML file, template $WEBDONE_THTML = "$ROOTDIR/done_t.html"; # partial HTML file, template $WEBDONE_HTML = "done$WORKID.html"; # complete HTML file (created in $WORKDIR) $DEBUG = 0; # 0 no debug messages, 1 some messages, 2 more. # Debug messages may go to Apache error_log at the beginning, but # once the LOGFILE/MSGFILE is created, they will go there. $CGI::POST_MAX=1024 * 600; # max size posts accepted, bytes # Note that the PDF file generated is around 4 times image sizes! $ENV{'PATH'}="/bin:/usr/bin:/usr/local/bin:/usr/local/netpbm/bin:/home/cgi/bin"; # security blanket (make sure all folders/files are non-writeable by others!) # following may be left alone, in most cases $ENV{'SHELL'} = "/bin/sh"; $ENV{'TMPDIR'} = $WORKDIR; $ENV{'TEMP'} = $WORKDIR; $ENV{'TZ'} = "EST5EDT"; delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; # Make %ENV safer # constants ---------------------------------------------------------- # --- MRKR_* variables are strings found in input HTML template files, # to be replaced with job-specific values $MRKR_HOSTNAME = "MRKR_HOSTNAME"; $MRKR_WEBDONEHTML = "MRKR_WEBDONEHTML"; $MRKR_PDF = "MRKR_PDF"; $MRKR_POSTSCRIPT = "MRKR_POSTSCRIPT"; $MRKR_GIF = "MRKR_GIF"; $MRKR_INPUT = "MRKR_INPUT"; $MRKR_SHOWSTATUS = "MRKR_SHOWSTATUS"; $MRKR_SYSERROR = "MRKR_SYSERROR"; $MRKR_SUCCESS = "MRKR_SUCCESS"; $MRKR_ANYERROR = "MRKR_ANYERROR"; $MRKR_GIFERROR = "MRKR_GIFERROR"; $MRKR_MAKEGIF = "MRKR_MAKEGIF"; $MRKR_CDLERROR = "MRKR_CDLERROR"; $MRKR_MSGFILE = "MRKR_MSGFILE"; $MRKR_TIMETAKEN = "MRKR_TIMETAKEN"; $MRKR_DONTREDIRECT = "MRKR_DONTREDIRECT"; $SAVINPUT="inp$WORKID.txt"; # exact copy of form input string, saved for user #--- executables - since am setting PATH, no need to give full path for each $REDIRECT="< /dev/null 2>&1"; # -- cmd 1: $CDLBL_E = "cdlabelgen $REDIRECT"; # -- cmd 2: $PS2PDF_E = "ps2pdf $WORKFILE.ps $REDIRECT"; # -- cmd 3: $PS2PGM_E = "gs -q -dNOPAUSE -dBATCH -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -r72 -sDEVICE=pgmraw -sPAPERSIZE=letter -sOutputFile=$WORKFILE.pgm -f $WORKFILE.ps $REDIRECT"; # gs options: # - made it anti-alias text and graphics (TextAlphaBits and Graphics...) # - pgm (gray scale) is faster and 66% smaller file than ppm (full color) # pgmraw is even more smaller, and is 10 times faster too, for large files! # -- cmd 4: $PGM2GIF_E = "(pnmcrop $WORKFILE.pgm | ppmtogif -interlace) 2>&1 > $WORKFILE.gif"; #color gif? (do jpeg instead?): $PGM2GIF_E = "(pnmcrop $WORKFILE.ppm | ppmquant 256 | ppmtogif -interlace) 2>&1 > $WORKFILE.gif"; # -- cmd 5: $CIMAGEFILE = "cvr$WORKID"; $TIMAGEFILE = "tra$WORKID"; $C_JPG2EPS_E = "jpeg2ps -r 72 -o $CIMAGEFILE.eps $CIMAGEFILE.jpg 2>&1"; $T_JPG2EPS_E = "jpeg2ps -r 72 -o $TIMAGEFILE.eps $TIMAGEFILE.jpg 2>&1"; # -- cmd 6: # PostScript cannot handle Progressive JPEG's, so have to run # jpegtran on every input JPG file to convert it to baseline JPEG $C_JPGTRAN_E = "jpegtran $CIMAGEFILE.jpg 2>&1 > $CIMAGEFILE.tmp && mv $CIMAGEFILE.tmp $CIMAGEFILE.jpg "; $T_JPGTRAN_E = "jpegtran $TIMAGEFILE.jpg 2>&1 > $TIMAGEFILE.tmp && mv $TIMAGEFILE.tmp $TIMAGEFILE.jpg "; #----------------------------------------------------------------------------- # initialize $status_count = -2; $dontredirect = ""; # make this 1 to prevent automatic redirect in WEBWAIT_THTML $time_taken = 0; $errflag = 0; $errcmd = ""; $hostname = ""; select((select(STDOUT), $| = 1)[0]); # autoflush # output HTML page headers, rest of HTML is output by copying WEBWAIT_THTML print CGI::header(); open(LOGFILE, ">> $LOGFILE") or myexit("Could not open log file ($LOGFILE): $!"); select((select(LOGFILE), $| = 1)[0]); # autoflush # all STDERR output is caught in local log file, so any perl errors # or uncaught STDERR from commands goes here, instead of the global # apache log file open (STDERR, '>>& LOGFILE') or myexit("Could not redirect STDERR to log file ($LOGFILE): $!"); umask(0); chdir $WORKDIR or myexit("cd ($WORKDIR) failed: $!"); open(MSGFILE, ">> $MSGFILE") or myexit("Could not open message file ($MSGFILE): $!"); select((select(MSGFILE), $| = 1)[0]); # autoflush open(WEBWAIT_THTML, "< $WEBWAIT_THTML") or myexit("Could not open WEBWAIT_THTML file ($ROOTDIR/$WEBWAIT_THTML): $!"); open(WEBDONE_THTML, "< $WEBDONE_THTML") or myexit("Could not open WEBDONE_THTML file ($ROOTDIR/$WEBDONE_THTML): $!"); open(WEBDONE_HTML, "> $WORKDIR/$WEBDONE_HTML") or myexit("Could not open WEBDONE_HTML file ($ROOTDIR/$WEBDONE_HTML): $!"); $datestr = localtime($start_time); print MSGFILE "[$datestr]: Starting job in directory $WORKDIRNAME\n"; # ----- file WEBWAIT opened, can send output... # start_html etc is not used - instead, a template HTML file is read # in and output to STDOUT &print_cgihtml($MRKR_SHOWSTATUS); # keep copying until MRKR_SHOWSTATUS line... print &show_status(); #---------------------------------------------------------------- # collect user input $query = new CGI; getopt('t:'); # -t is test mode. Filename is used as $incontents if (! $opt_t ) { # in some cases, I've seen these variables come in as "undefined", # so to suppress perl -w warnings, using the || '' construct below $hostname = $query->remote_host() || ''; $useragent = $query->user_agent() || ''; $referer = $query->referer() || ''; $intitle = $query->param('title') || ''; $insubtitle = $query->param('subtitle') || ''; $inclogo = $query->param('clogo') || ''; $intlogo = $query->param('tlogo') || ''; $incimage = $query->param('cimage') || ''; $intimage = $query->param('timage') || ''; $incimagefile = $query->upload('cimagefile') || ''; # get file handle $intimagefile = $query->upload('timagefile') || ''; # get file handle $incontents = $query->param('contents') || ''; $incontents =~ s/$CR?$LF/\n/g; # fix all CR/LF chars $incdcase = $query->param('cdcase') || 'normal'; $innotrayhd = $query->param('notrayheading') || ''; $inscaleitems = $query->param('scaleitems') || ''; $inmakegif = $query->param('makegif') || ''; $ina4paper = $query->param('a4paper') || ''; $insplititems = $query->param('splititems') || ''; $infile = $query->param('filename') || ''; } else { $hostname = qq(testing mode "-t $opt_t"); $useragent = ''; $referer = ''; $infile = ''; $intitle = "Testing Title"; $insubtitle = "Testing Subtitle"; $incimage = 'mp3.eps'; $intimage = 'cdda.eps'; $incimagefile = ''; $intimagefile = ''; $incdcase = 'normal'; $innotrayhd = 0; $inscaleitems = 0; $inmakegif = 1; $insplititems = 0; $ina4paper = 0; $inclogo = 1; $intlogo = 0; open(INPUT, "$opt_t") or myexit("Could not open input file (-t $opt_t) [Make sure full path given -t /tmp/x.txt etc]: $!"); print MSGFILE "opened input file $opt_t\n" if ($DEBUG >= 1); while () { # read each line to get correct EOLN value for this platform (works?) s/$CR?$LF/\n/; # variables from Socket package $incontents .= $_; } close INPUT; } $datestr = localtime($start_time); print LOGFILE "$WORKDIRNAME cdinsert [$datestr] $hostname - started\n"; print MSGFILE "[$datestr] checking cgi_error...\n"; $cgierror = $query->cgi_error(); # post too big, or user hit STOP, etc... # in some rare cases, cgi_error() takes over 2 minutes, not sure what # is wrong, probably a remote browser problem? if ($cgierror) { if ($cgierror =~ /413/) { myexit("Received too much data, can receive max of " . int($CGI::POST_MAX/1024) . "KBytes."); } else { myexit($cgierror); } } # have now read in all files user may have uploaded, beginning processing $start_processing_time = time(); $datestr = localtime(time()); print MSGFILE "----------------------------------------------------\n"; print MSGFILE "[$datestr] Got these values from the form:\n"; my %params = $query->Vars; while (($key, $value) = each %params) { # assuming value is single string - if multi-valued, need # to split on \0 to get array of values... $value = "" if ( $key =~ /^contents$/ ); print MSGFILE " $key = '$value'\n"; } print MSGFILE "Some environment vars:\n"; # print MSGFILE " remote_host = '$hostname'\n"; print MSGFILE " user_agent = '$useragent'\n"; print MSGFILE " referer = '$referer'\n"; print MSGFILE "----------------------------------------------------\n"; $gotstring = ($incontents =~ /\S+/); $gotfile = ($infile =~ /\S+/); if ($gotfile) { # ignore $gotstring, file takes precedence if ($gotstring) { print MSGFILE "** Warning: user entered text as well as filename, will append file to entered text.\n"; } while (<$infile>) { s/$CR?$LF/\n/; # correct end-of-line (variables from Socket package) $incontents .= $_; } print MSGFILE "... read in uploaded file: $infile\n"; # if the file is not text, but binary, reject it, stop script later.. # (stop later because file is saved before exiting, so we can debug) $null_in_contents = ($incontents =~ /\000/); } # some people post binary files here, and ghostscript gs hangs on # such text, so have to remove invalid characters # don't really know a sure-fire way of detecting binary files or # deleting all non-printable chars (ISO-Latin1, ASCII, etc??) # so, doing something that is probably good enough in most cases # this is just more protection - there may be code above to return # errors if a non-text file is uploaded for the list of items. @items = split(/\n/, $incontents); $num_items = $#items + 1; $incontents = ""; for (@items) { # remove all control chars, and all nulls s/[[:cntrl:]\000]//g; # restrict each line to max 256 characters $_ = substr($_, 0, 256); $incontents .= $_; $incontents .= "\n"; # add back the end-of-line char } @items = (); # not needed anymore $datestr = localtime(time()); print MSGFILE "[$datestr]: writing input to $SAVINPUT\n"; # save users string, to pass to exe, and in case users need to use it again open(OUTPUT, "> $SAVINPUT") or myexit("Could not open output file to save form input ($SAVINPUT): $!"); print OUTPUT $incontents; close OUTPUT; print MSGFILE "--> input text copied to $SAVINPUT.\n" if ($DEBUG >= 1); # now exit if file was bad - NULLs in it, etc. if ($null_in_contents) { myexit("\"$infile\" is not a ASCII text file. Only ASCII text content should be uploaded for list of items."); } # ---------------------------------------------------------------------- # untaint variables... $incimage =~ /([\d\w\-\.]*)/; # no / allowed in name $incimage = $1; $intimage =~ /([\d\w\-\.]*)/; # no / allowed in name $intimage = $1; $insplititems =~ /([\d\w\-\.]*)/; # no / allowed in name $insplititems = $1; $ina4paper =~ /([\d\w\-\.]*)/; # no / allowed in name $ina4paper = $1; # not really passing these as args, but perl -T complains, so clean them... $incdcase =~ /([\d\w\-\.]*)/; # no / allowed in name $incdcase = $1; $innotrayhd =~ /([\d\w\-\.]*)/; # no / allowed in name $innotrayhd = $1; $inscaleitems =~ /([\d\w\-\.]*)/; # no / allowed in name # Title and Subtitle should use entire string as entered by user # but - do escape any non-alphanumeric character, this should take # care of shell metacharacters such as " $ etc # Don't quote the title or subtitle: # single quotes are a problem since another \' inside the string gets ignored. # double quotes are a problem since most \ 's are preserved \) remains \) # s/([`"\$\\])/\\$1/g; # use this if enclosing title in double quotes " # s/(\W)/\\$1/g; # use this if NOT enclosing title in any quotes " or ', # is safest since every non-alpha-numeric character is escaped. $intitle =~ /(.*)/; # yes, really need this. $intitle = $1; $intitle =~ s/(\W)/\\$1/g; $insubtitle =~ /(.*)/; # yes, really need this. $insubtitle = $1; $insubtitle =~ s/(\W)/\\$1/g; print MSGFILE "after untaint: title($intitle) subtitle($insubtitle) clogo($inclogo) tlogo($intlogo)\n" if ($DEBUG >= 1); # read in any uploaded images $datestr = localtime(time()); print MSGFILE "[$datestr]: reading in any uploaded JPG files\n"; if ($incimagefile) { if ($incimage) { print MSGFILE "** Warning: user selected built-in Cover Image and uploaded Image, ignoring built-in.\n"; } $incimage = ""; copy($incimagefile, "$CIMAGEFILE.jpg") or myexit("Could not copy uploaded file ($incimagefile) ($CIMAGEFILE.jpg): $!"); close($incimagefile); &do_cmd($C_JPGTRAN_E) || &do_cmd($C_JPG2EPS_E); $dontredirect = "1" if ($errflag); # important command failed $incimage = $errflag ? "": "$CIMAGEFILE.eps"; } # read in any uploaded images if ($intimagefile) { if ($intimage) { print MSGFILE "** Warning: user selected built-in Tray Image and uploaded Image, ignoring built-in.\n"; } $intimage = ""; copy($intimagefile, "$TIMAGEFILE.jpg") or myexit("Could not copy uploaded file ($intimagefile) ($TIMAGEFILE.jpg): $!"); close($intimagefile); &do_cmd($T_JPGTRAN_E) || &do_cmd($T_JPG2EPS_E); $dontredirect = "1" if ($errflag); # important command failed $intimage = $errflag ? "" : "$TIMAGEFILE.eps" ; } # compute -S and -T scale factors. # use the special value "0.0" if image is to be printed as background, # otherwise use no scaling (1.0 scale factor). $clogoscale = ($inclogo) ? "1.0" : "0.0"; # $tlogoscale = ($intlogo) ? "1.0" : "0.0"; # 0.0 == fill1 - interior only if ($incdcase =~ /^normal/) { $tlogoscale = ($intlogo) ? "1.0" : "fill2"; # fill2: fill endcaps too } else { $tlogoscale = ($intlogo) ? "1.0" : "fill1"; # fill1: just fill tray } # ---- compute page offset for A4 and gs command modifications if ($ina4paper) { $PS2PGM_E =~ s/PAPERSIZE=letter/PAPERSIZE=a4/; $ina4paper = "-y 1.5"; # default $ina4paper = "-y 0.8" if ($incdcase =~ /^(dvd)|(envelope)/); } #----------------------------------------------------------------------------- $datestr = localtime(time()); print MSGFILE "[$datestr] $hostname :: Starting programs...\n"; print MSGFILE "----------------------------------------------------\n"; # Jan02: accept empty input, most common error, so better to accept it # ($gotstring || $gotfile || $intitle || $insubtitle || $incimage || $intimage) # or myexit("Nothing to do - empty input - no fields entered!"); # 1: run cdlabelgen to create .ps file $cmd = $CDLBL_E; # preparing a push, in case I need to use system() @cmdargs = (); push(@cmdargs, "-c $intitle") if ($intitle); # no quotes around title... # don't use single quotes, embedded \' causes problems in title/subtitle push(@cmdargs, "-s $insubtitle") if ($insubtitle); # no quotes around title... push(@cmdargs, "-e '$incimage'") if ($incimage); push(@cmdargs, "-S '$clogoscale'") if ($incimage); push(@cmdargs, "-E '$intimage'") if ($intimage); push(@cmdargs, "-T '$tlogoscale'") if ($intimage); push(@cmdargs, "-f $SAVINPUT"); push(@cmdargs, "-D"); push(@cmdargs, "-m") if ($incdcase =~ /^slimcase/); push(@cmdargs, "-M") if ($incdcase =~ /^envelope/); push(@cmdargs, "--create-dvd-inside") if ($incdcase =~ /^dvdinside/); push(@cmdargs, "--create-dvd-outside") if ($incdcase =~ /^dvdoutside/); push(@cmdargs, "-p") if (! $inscaleitems); push(@cmdargs, "-b") if ($innotrayhd); push(@cmdargs, $ina4paper) if ($ina4paper); # if number of items is very large, print some items on the cover also push(@cmdargs, "-v " . int($num_items/2)) if ($num_items > 250 || $insplititems); push(@cmdargs, "-o $WORKFILE.ps"); # cdlabelgen arguments: # -c Set the category (title) for the CD # -s # -d default: YYCC-MM-YY # -D don't print date # -f input filename # -e # -E # -m for slim cd cases # --create-dvd-inside for inside inserts for DVD cases # -M for CD envelope # -p clip text - don't scale down item (if required to fit to a column) # -b don't print the plaque (title/subtile) on tray_card # -y 1.5 or -y 0.8 for A4 paper # system($cmd, @cmdargs); $returncode = ($? >> 8); # could not make the above work, anyway, need to call do_cmd, so using ` ` $cmd = join(' ', $CDLBL_E, @cmdargs); &do_cmd($cmd) if (!$errflag); $dontredirect = "1" if ($errflag); # main command failed, don't redirect # 2: run PDF conversion &do_cmd($PS2PDF_E) if (!$errflag); if ($inmakegif) { # 3: run GIF conversion - intermediate - create .pgm file &do_cmd($PS2PGM_E) if (!$errflag); # 4: run GIF conversion - final - convert pgm to gif &do_cmd($PGM2GIF_E) if (!$errflag); } # if $inmakegif print " Done!\n

\n"; # status messages to web... print MSGFILE "commands executed. \$errflag='$errflag' \$errcmd='$errcmd'\n"; # remove intermediate log files unlink("$WORKFILE.pgm") unless ($opt_t || $DEBUG >= 2); $end_time = time(); #NOTUSED $processing_time_taken = $end_time - $start_processing_time; $receive_time_taken = $start_processing_time - $start_time; $time_taken = $end_time - $start_time; $datestr = localtime($end_time); $datestr = "$WORKDIRNAME cdinsert [$datestr] took $time_taken secs "; $datestr .= "(download $receive_time_taken) " if ($gotfile || $incimagefile || $intimagefile); $datestr .= "[error]" if ($errflag); $datestr .= "\n"; print LOGFILE $datestr; print MSGFILE $datestr; print MSGFILE "----------------------------------------------------\n"; # copy output HTML page show output or error, as appropriate while () { if ($errflag) { # depending on error, uncomment particular lines in WEBDONE_THTML next if (&check_marker($_, $MRKR_ANYERROR)); if ($errcmd =~ /$CDLBL_E/) { next if (&check_marker($_, $MRKR_CDLERROR)); } elsif ($errcmd =~ /$PGM2GIF_E/) { next if (&check_marker($_, $MRKR_GIFERROR)); } next if (&check_marker($_, $MRKR_SYSERROR)); # #errcmd not CDLBL or PGMGIF } else { # no error, uncomment the SUCCESS lines next if (&check_marker($_, $MRKR_SUCCESS)); } next if ($inmakegif && &check_marker($_, $MRKR_MAKEGIF) && !$errflag); print WEBDONE_HTML &replace_markers($_); } close(WEBDONE_HTML); # complete rest of HTML from this CGI script, will redirect to WEBDONE &print_cgihtml(""); close(WEBDONE_THTML); close(WEBWAIT_THTML); close(LOGFILE); close(MSGFILE); exit($errflag); #----------------------------------------------------------------------------- # Subroutines sub show_status { my($cmd) = @_; $status_count++; if ($status_count < 0) { return ("Working . .
\n"); } # if cmd contains | char, look for last | and the command after that # otherwise, use the first word as the command ($cmd =~ /\|\s+(\w+)[^|]*$/) || ($cmd =~ /\s*(\w+)/); # $1 is last command. return "   ($1) . .
\n" if ($1); return "   $status_count . .
\n"; } #----------------------------------- sub check_marker { # check if $str contains the given marker string (if $in marker != "") my($str, $in) = @_; $in && $str =~ /\b$in\b/; } #----------------------------------- sub replace_one { # replaces $str in calling function (if $in marker != "") my($str, $in, $out) = @_; $in && $_[0] =~ s/\b$in\b/$out/; } #----------------------------------- sub replace_markers { my($str) = @_; &replace_one($str, $MRKR_HOSTNAME, "$hostname"); &replace_one($str, $MRKR_WEBDONEHTML, "$WORKHTTP/$WEBDONE_HTML"); &replace_one($str, $MRKR_INPUT, "$WORKHTTP/$SAVINPUT"); &replace_one($str, $MRKR_PDF, "$WORKHTTP/$WORKFILE.pdf"); &replace_one($str, $MRKR_GIF, "$WORKHTTP/$WORKFILE.gif"); &replace_one($str, $MRKR_POSTSCRIPT, "$WORKHTTP/$WORKFILE.ps"); &replace_one($str, $MRKR_MSGFILE, "$WORKHTTP/$MSGFILENAME"); &replace_one($str, $MRKR_TIMETAKEN, "$time_taken"); &replace_one($str, $MRKR_DONTREDIRECT, "$dontredirect"); return $str; } #----------------------------------- sub print_cgihtml { my($str) = @_; # print lines in the CGI output file... until $str is encountered # when completed this will finish the # body, and do the javascript redirect to webdone.html while () { last if ($str && /$str/); print &replace_markers($_); } # this completes the output HTML file (no need to print CGI::end_html) } #----------------------------------- sub do_cmd { my($cmd) = @_; my ($t1, $td); $datestr = localtime(time()); print MSGFILE "[$datestr]: do_cmd\n"; print &show_status($cmd); $t1 = time(); $out = `$cmd`; $returncode = ($? >> 8); $td = time() - $t1; print MSGFILE qq("$cmd" executed\n -- Took $td seconds, returns $returncode\n); if ($returncode != 0) { print "

\n"; print "Session ID# $WORKDIRNAME - an error occured running a command.\n
\n"; print "Command: ", escapeHTML($cmd), ", \$? is $?\n
"; $out = escapeHTML($out); $out =~ s/\n/\n
/; print qq($out\n



\n); $errflag++; $errcmd = $cmd; print MSGFILE "Error occurred:\n"; } print MSGFILE "$out\n---------------------\n"; $returncode; } #----------------------------------- sub sighandler { unlink("$WORKFILE.pgm"); # this file can get big, so making sure it is gone $datestr = localtime(time()); $str = "$WORKDIRNAME cdinsert [$datestr] user terminated --\n"; print LOGFILE $str; print MSGFILE $str; close(WEBDONE_HTML); close(WEBWAIT_THTML); close(WEBDONE_THTML); close(LOGFILE); close(MSGFILE); exit($errflag); } #----------------------------------- sub myexit { # if myexit() is called after WEBWAIT_THTML copied to STDOUT, # the automatic redirect in that file needs to be suppressed $dontredirect = "1"; $errflag++; my($mesg) = @_; print "

\nSession ID# $WORKDIRNAME - Error - $mesg\n


"; # displayed in middle of WEBWAIT_THTML $datestr = localtime(time()); $str = "$WORKDIRNAME [$datestr] Error - $mesg\n"; print STDERR $str; # goes to Apache error_log or LOGFILE print MSGFILE $str; # complete rest of HTML from this CGI script &print_cgihtml(""); close(WEBDONE_HTML); close(WEBWAIT_THTML); close(WEBDONE_THTML); close(LOGFILE); close(MSGFILE); exit($errflag); } #---------------------------------------- # Try a few times to make unique temp directory by appending chars if needed sub mktempdir { my $dir = shift; # directory to create tmp dir in my $try = shift; # prefix to use for directory name my $n = shift; # a numeric suffix to use - is incremented until unique my $done = 0; my $i; my $dirname; umask(0); foreach $i (0..9) { $dirname = "$try-$n"; $done = mkdir("$dir/$dirname", 0777); last if ($done); $n++; } $done || myexit("mktempdir: mkdir in ($dir) with prefix ($try-$n) failed: $!"); $done ? $dirname : ""; } #-----------------------------------------------------------------------------