#!/usr/bin/perl
#	-*- perl -*-
#	C. Alex. North-Keys
#	Incept: 2007-06-07 21:58:37 CDT (Jun Thu) 1181271517
#	render.cgi
#   accept a New York Times' .puz file for input and render it.
#
#	requires the following in a relevant .htaccess file:
#    <Files upload.cgi>
#      AddOutputFilter INCLUDES .cgi
#    </Files>

use strict;
use CGI qw/:standard -private_tempfiles/;
use IO::Handle;  
use IPC::Open2;

my $ssi_wrapper_prefix = '/~erlkonig/';
# my $ssi_wrapper_prefix = '';

sub HtmlHeaderSSI	# args: title
{
	my $swp = $ssi_wrapper_prefix;
	my $html = (''
				. "Content-type: text/html\n\n"
				. "<html>\n"
				. "<head>\n"
				. '<!--#include virtual="'.$swp.'@subhead.shtml" -->' . "\n"
				. '<style type="text/css">'. "\n"
				. '.success { font-weight: bold; color: #070; }'. "\n"
				. '.error { font-weight: bold; color: #900; }'. "\n"
				. '</style>'. "\n"
				. "</head>\n"
				. '<!--#include virtual="'.$swp.'@bodystart.shtml" -->' . "\n"
			   );
}

sub HtmlTrailerSSI
{
	my $swp = $ssi_wrapper_prefix;
	my $html = ('<!--#include virtual="'.$swp.'@bodyend.shtml" -->' . "\n"
				."</body></html>\n"
			   );
}

sub QueryTable
{
	my ($query) = @_;
	my $html = ("<table border>\n"
				."<caption>Request Data</caption>\n");
	my @params = $query->param;
    my ($key);
    foreach my $key (sort @params)
    {
        my @data = $query->param($key);
		$html .= ('<tr valign=top><th>' . $key . "\n"
				  ."<td><p>\n");
		$html .= join("\n", @data);
        $html .= ("</p>\n"
				  ."\n");
    }
	$html .= "</table>\n";
	return $html;
}

sub EnvironmentTable
{
	my $html =
		("<table border>\n"
		 . "<caption>Environment</caption>\n");
	my ($key);
	foreach $key (sort keys(%ENV)) {
		my ($value) = $ENV{$key};
		$html .=
			('<tr valign=top><th align=left>' . $key . "\n"
			 . "<td><p>\n"
			 .$value
			 ."</p>\n"
			 ."\n");
	}
	$html .= "</table>\n";
}

sub Sanitize
{
    my ($text) = @_;
    $text =~ y/-A-Za-z0-9.%_+//cd; # sanitization
    return $text;
}

sub SanitizePath				# $pathname -- $relative-downward-only-path
{
    my ($text) = @_;
    $text =~ y/-A-Za-z0-9.%_+\///cd; # sanitization - keep asterisks
	$text =~ s@^[\./]*/@/@;			 # toss all initial slashes and dots (to /)
	$text =~ s@/\.\./@@g;			 # toss all embedded /../
	$text =~ s@/$@@;				 # toss trailing /
    return $text;
}

sub GetPuzzleData
{
	my ($query) = @_;
	my $data = '';
	my @fhs = $query->param("file_to_upload");
	my $fh = $fhs[0];
	my @infos =  $query->uploadInfo($fh);
	foreach my $info (@infos) {
		my $type = $info->{'Content-Type'};
		if(defined($type)) {
			while(<$fh>) {
				$data .= $_;
			}
		}
	}
	return $data;
}

sub SubdirAsUL					# $directory -- $html-ul/li list
{
	my($dir, $depthleft) = @_;
	my $html;
	if(opendir(DIR, $dir)) {
		my @entries = grep { /^[^.]/ ; } readdir(DIR);
		closedir(DIR);
		$html .= "<ul>\n";
		foreach my $entry (@entries) {
			my $sub = "$dir/$entry";
			if(-d "$sub" && ! -l "$sub") {
				$html .=  "<li>$entry";
				if($depthleft > 1) {
					$html .= &SubdirAsUL("$sub", $depthleft - 1);
				}
				$html .= "</li>\n";
			}
		}
		$html .= "</ul>\n";
	} else { $html .= '<span class="error">Target area inaccessible!</span.'; }
	return $html;
}

sub RenderPuzzle($$$$)
{
	my ($data, $answers, $format, $key) = @_;
	my $output  = undef;
	my $command = undef;
	my $needs_html_wrapper = 0;

	if($format =~ m/^HTML$/i) {
		$command = './puz-decode';
		$needs_html_wrapper = 1;
	} elsif($format =~ m/^PostScript$/i) {
		$output .= 'Content-type: application/postscript' . "\n\n";
		$command = './puz-decode -P';
	} else {
		$output = "<html><body>Bad format $format</body></html>";
	}
	if($answers) {
		$command .= ' -a'; # note leading space
	}
	if($key) {
		$command .= ' -k' . $key; # "-k1234" for example.
	}
	if($command) {
		my $pid = open2(\*RESULTS, \*COMMANDS, $command);
		if($pid) {
			COMMANDS->autoflush(1);
			print(COMMANDS $data);
			close(COMMANDS);
			$output .= join('', <RESULTS>);
			close(RESULTS);
			waitpid($pid, 0);
		}
	}
	return ($output, $needs_html_wrapper);
}

sub Main
{
	my $query = new CGI;

	my $puz = GetPuzzleData($query);
	my $format   = $query->param("output_format");
	my $answers  = $query->param("show_answers") =~ m/^yes/i;
	my $key      = $query->param("scramble_key");
	if($key !~ /^\d\d\d\d$/) { $key = undef; }

	my ($rendered, $needs_html_wrapper)
		= RenderPuzzle($puz, $answers, $format, $key);

	if($needs_html_wrapper) {
		my $html = ''
			. &HtmlHeaderSSI() 
			. (''
#			   . "<samp>puzdate: $puz</samp>\n"
#			   . &QueryTable($query)
			   . $rendered
#			   . &EnvironmentTable()
			   )
			. &HtmlTrailerSSI();
		print $html;
	} else {
		print $rendered;
	}
	exit 0;
}

&Main();

#-------------eof

