Listing 4, result.pl

#!/usr/bin/perl -w
# Cgi to show customer's orders
# Secure path
$ENV{PATH} = '/bin/:/usr/bin:/usr/local/bin';
# Using CGI modules and creating a new CGI instance
use CGI;
$query = new CGI;
# Defining some variables
$htmltpl  = '/home/httpd/html/result.html';
$basepath = '/var/tables/acmeinc/';
$cusfile  = $basepath . 'customer.rdb';
$ctlgfile = $basepath . 'catalog.rdb';
# Getting customer name from the form
$cusname  = $query->param('cusname');
# Avoid buffer overflow (maximum 50 chars) and command execution
# from the customer name: this is a security countermeasure
$cusname = substr($cusname, 0, 50);
$cusname =~ s/\///g;
$cusname =~ s/#//g;
$cusname =~ s/\n//g;
$cusname =~ s/"//g;
$cusname =~ s/'//g;
$cusname =~ s/\`//g;
$cusname =~ s/!//g;
$cusname =~ s/;//g;
$cusname =~ s/<//g;
$cusname =~ s/>//g;
# Extracting customer code for further queries and striping insecure stuffs
$cuscode = `nosql row 'NAME=="$cusname"' < $cusfile | nosql column CODE | nosql body`;
$cuscode =~ s/\///g;
$cuscode =~ s/#//g;
$cuscode =~ s/!//g;
$cuscode =~ s/\n//g;
$cusname =~ s/"//g;
$cusname =~ s/\`//g;
$cusname =~ s/;//g;
$cusname =~ s/<//g;
$cusname =~ s/>//g;
$cuscode =~ s/\s*//g;
# Getting customer datafile that is usually the code plus the ".rdb"
# extension
$datafile = $basepath . "received/" . $cuscode . ".rdb";
# Getting the rows containing the query of the pending orders
#
@cusdata = `nosql cat $datafile | nosql join -j PROD - $ctlgfile |
nosql addcol SUBTOTAL | nosql compute 'SUBTOTAL = QTY*PRICE' | nosql
column PROD DESC QTY PRICE SUBTOTAL | nosql body`;
# If no rows found, then customer may not exists or has no pending
# orders
if (@cusdata == 0) {
        &log_and_die("No records found on the specified customer")
};
# Calculating total amount due
chop($total = `nosql cat $datafile | nosql join -j PROD - $ctlgfile |
nosql addcol SUBTOTAL | nosql compute 'SUBTOTAL = QTY*PRICE' | nosql
subtotal -T SUBTOTAL | nosql body`);
# If the string is empty, then something went wrong.
if ($total eq '') {
        &log_and_die("Cannot calculate total")
};
# This opens html template file for reading and
# it's associated to the standard input space ($_)
open(HTMFILE, $htmltpl) || &log_and_die("Can't open file $htmltpl");
$_ = join("", <HTMFILE>);
close(HTMFILE);
# Keeping out newlines.
s/\n//g;
# Transforming multiple spaces into one,
s/\s+/ /g;
# Finding stanza into template and we separate
# header, footer and the body (that has to be repeated)
/(.+)<\s*!--\s*here\s+starts\s+nosql\s+stanza\s*--->(.+)<\s*!--\s*here
\s+ends\s+nosql\s+stanza\s*--\s*>(.+)/i ;
#
# Copying found pattern on temp vars
my $header = $1;
my $body   = $2;
my $footer = $3;
# substituting keywords on header and footer with appropriate values
$header =~ s/##NAME##/$cusname/;
$footer =~ s/##TOTAL##/$total/;
# Print html content type and template header
print $query->header("text/html");
print $header;
# Repeating values substitution in stanza for each query row
foreach $data (@cusdata) {
        my $tmpbody = $body;
        my ($prod, $desc, $qty, $price, $subtotal) = split(/\t/, $data);
        $tmpbody =~ s/##PROD##/$prod/;
        $tmpbody =~ s/##DESC##/$desc/;
        $tmpbody =~ s/##QTY##/$qty/;
        $tmpbody =~ s/##PRICE##/$price/;
        $tmpbody =~ s/##SUBTOTAL##/$subtotal/;
        print $tmpbody;
}
# Print template footer
print $footer;
#
sub log_and_die
{
        # Get parms
        my $message = shift;
        # Print error message to user's browser
        print $query->header("text/html");
        print $query->start_html(-title=> "Error processing data");
        print "<P>An unrecoverable error occurred: $message</P>\n";
        print $query->end_html;
        exit(1);
};