Gossamer Forum
Home : General : Perl Programming :

Passing Values ...

Quote Reply
Passing Values ...
Hi, I have two scripts, one called order.cgi and the other result.cgi. order.cgi basically processes values entered from a form, and result.cgi displays the results of order.cgi

It all works fine, excepts I am having troubles displaying the 'REASON' field from order.cgi in result.cgi.

If anyone could work this out, it would be most helpful.

** ORDER.CGI
#-----------------------------------------------------------------------#
# main: Main body of the script. #
# params: <none> #
# returns: <exit> #
#-----------------------------------------------------------------------#
sub main {

# Find out what parameters were passed to the script.
my $query = CGI->new();
my $user = $query->param("user");
my $reason = $query->param("reason");
my $amount = $query->param("amount");

# Clean up our parameters a bit. Empty values tend to be passed as
# an empty string instead of an undefined value, so check for them and
# undefine them.
if ($user eq "") {
$user = undef;
}
if ($reason eq "") {
$reason = undef;
}
if ($amount eq "") {
$amount = undef;
}

# If we don't have any values then print the first webpage to prompt
# for that information.
if (!defined($user) && !defined($reason) && !defined($amount)) {
print_loghtml();
}

# Check for each parameter individually and spit out an error if any of
# them are missing.
elsif (!defined($user)) {
weberror("You must enter your name.");
}
elsif (!defined($reason)) {
weberror("You must enter a reason for debiting someone's credit card.");
}
elsif (!defined($amount)) {
weberror("You must specify the amount to debit from the card.");
}

# Strip out any '$' characters from the amount, just in case.
$amount =~ s/\$//g;

# Check the format of the amount. If it has a decimal point, followed
# by 0-2 digits, then assume it's of the form $1.23. Convert that to
# cents (ie 123c)
if ($amount =~ /^(\d*)\.(\d{0,2})$/) {
$amount = "$1$2";
}

# Otherwise if it's just a number, assume it's just dollars and multiply
# by 100.
elsif ($amount =~ /^(\d+)$/) {
$amount = $amount * 100;
}

# otherwise, we don't recognise this format. Throw an error.
else {
weberror("Error: Invalid amount.");
}

# Check to make sure the amount is sane (non-zero).
if ($amount <= 0) {
weberror("Error: Can't debit card for \$0.00");
}

# Strip newlines, carriage returns and pipes from the reason so we
# don't muck up the log files.
$reason =~ s/[\n\r\|]/ /g;

# Get the next transaction number.
my $refid = get_refid();
if (!defined($refid)) {
weberror("Error: Failed to get next reference number.");
}

# Print to the human readable log.
logmsg($refid, $user, $amount, $reason);

# Add our entry to the transaction log (the non-human readable log).
logtrans($refid, $user, $amount, $reason);

# If all is OK by this point, print out the web page requesting the
# credit card details.
print_cchtml($refid, $amount, $reason, $user);
}


#-----------------------------------------------------------------------#
# get_refid: Gets the next reference number (or transaction number) #
# from the file. #
# params: <none> #
# returns: (int) refid #
#-----------------------------------------------------------------------#
sub get_refid {
my $id;
open IN, "+<$reference" or return(undef);
flock(IN, 2);
while (<IN>) {
$id = $_;
}
$id =~ s/\s//g;
if ($id !~ /^(\d+)$/) {
return(undef);
}
else {
$id++;
seek(IN, 0, 0);
print(IN $id);
truncate(IN, tell(IN));
}
close(IN) and flock(IN, 8);
return($id);
}


#-----------------------------------------------------------------------#
# logmsg: Prints the details of the requested transaction to the #
# log file with the current time and date. #
# params: (int) refid, (string) user, (int) amount, #
# (string) reason #
# returns: <none> #
#-----------------------------------------------------------------------#
sub logmsg {
my ($refid, $user, $amount, $reason) = @_;
my @now = localtime();

open LOG, ">>$logfile" or weberror("Failed to open $logfile: $!");
flock(LOG, 2);
my $string = sprintf("%04d/%02d/%02d %02d:%02d\|%s\|%s\|%s\|%s\n",
$now[5] + 1900, $now[4] + 1, $now[3], $now[2], $now[1], $refid,
$user, $amount, $reason);
print LOG $string;
close(LOG) and flock(LOG, 8);
chmod(0644, $logfile);
}


#-----------------------------------------------------------------------#
# logtrans: Log a transaction to file so that the details can be #
# retrieved later by the results script. #
# params: (int) refid, (string) user, (int) amount #
# returns: <none> #
#-----------------------------------------------------------------------#
sub logtrans {
my ($refid, $user, $amount, $reason) = @_;
if (!defined($refid) || !defined($user) || !defined($amount)) {
weberror("Error logging transaction: Insufficient data");
}

my $now = time();
my @lines;

open LOG, "+<$translog" or weberror("Failed to open $translog: $!");
flock(LOG, 2);
while (my $string = <LOG>) {
chomp($string);
my @line = split(/\|/, $string);
next if ($now - $line[0] > 86400);
push(@lines, $string);
}
seek(LOG, 0, 0);
my $string = sprintf("%d\|%d\|%s\|%d\|%s", $now, $refid, $user,
$amount, $reason);
push(@lines, $string);
print(LOG join("\n", @lines));
truncate(LOG, tell(LOG));
close(LOG) and flock(LOG, 8);
}


#-----------------------------------------------------------------------#
# print_loghtml: Prints the webpage requesting the staffmembers #
# details, amount to debit and reason. #
# params: <none> #
# returns: <exit> #
#-----------------------------------------------------------------------#
sub print_loghtml {
open HTML, "<$log_template" or weberror("Failed to open $log_template: $!");
my $body = join("", <HTML>);
close(HTML);

print header();
print $body;
exit;
}


#-----------------------------------------------------------------------#
# print_cchtml: Prints the web page requesting credit card details #
# to the browser with the appropriate values instead #
# of placeholders. #
# params: (int) refid, (int) amount, (string) reason #
# returns: <exit> #
#-----------------------------------------------------------------------#
sub print_cchtml {
my ($refid, $amount, $reason) = @_;

if (!defined($refid) || !defined($amount) || !defined($reason)) {
weberror("Error: Data has gone missing!");
}
my $pricestring = sprintf("\$%d.%02d", $amount / 100, $amount % 100);

open HTML, "<$debit_template" or weberror("Failed to open ".
"$debit_template: $!");
my $body = join("", <HTML>);
close(HTML);

$body =~ s/NICEDEBITAMOUNT/$pricestring/g;
$body =~ s/DEBITAMOUNT/$amount/g;
$body =~ s/DEBITREASON/$reason/g;
$body =~ s/REFERENCENUMBER/$refid/g;

print header();
print $body;
exit;
}



#-----------------------------------------------------------------------#
# weberror: Prints a web page displaying an error message to the #
# browse. #
# params: (string) msg #
# returns: <exit> #
#-----------------------------------------------------------------------#
sub weberror {
my ($msg) = @_;
if (!defined($msg)) {
$msg = "An unidentified error has occurred";
}

open HTML, "<$error_template" or die("Failed to open ".
"$error_template: $!. Actual error was $msg");
my $body = join("", <HTML>);
close(HTML);

$body =~ s/ERRORMESSAGE/$msg/g;

print header();
print $body;
exit;
}


** RESULT.CGI
#-----------------------------------------------------------------------#
# main: Main body of the results script. #
# params: <none> #
# returns: <exit> #
#-----------------------------------------------------------------------#
sub main {
my $query = CGI->new();
my $refid = $query->param('r');
my $msg = $query->param('m');
my $unparsed = $msg;

print(STDERR "[STAFFRESULT] $refid: $msg\n");
# Sanity check our reference number (it should be all digits).
if ($refid !~ /^(\w+)$/) {
weberror("Error: Invalid reference number received: $refid.");
}
$refid = $1;

# Sanity check the return message and split it into a return code and
# the actual message.
if ($msg !~ /^(\d{3})\s*(.+)$/) {
print STDERR "Invalid message $msg\n";
weberror("Error: Invalid message format received.");
}
my $code = $1;
$msg = $2;

# Get the transaction details out of the transaction log.
my $details = get_details($refid);

if (!defined($details)) {
weberror("Error retrieving details for transaction $refid");
}
# '200' means the transaction was successful.
if ($code eq "200") {
my $auth = $query->param('a');
my $sig = $query->param('s');
if ($auth !~ /^[\w\s]{1,6}$/) {
weberror("Invalid authorisation id format: $auth");
}
$auth = $1;

# Sanity check the format of the signature.
if ($sig !~ m/^([\w\/\+]+=)$/s) {
weberror("Invalid signature: $sig");
}
$sig = $1;

# The amount is in cents. Turn it into dollars.
my $amt = sprintf("%d.%02d", $details->{'AMOUNT'} / 100,
$details->{'AMOUNT'} % 100);

# Read in the HTML template, substitute our values and print.
open HTML, "<$success_template" or weberror("Failed to open ".
"$success_template: $!");
my $body = join("", <HTML>);
close(HTML);

$body =~ s/REFERENCENUMBER/$refid/g;
$body =~ s/DEBITAMOUNT/$amt/g;
$body =~ s/RETURNMESSAGE/$msg/g;
$body =~ s/RETURNCODE/$code/g;

open(OUT, ">>$completed") or weberror("Failed to open $completed: $!".
" (transaction was successful)");
flock(OUT, 2);
my @when = localtime($details->{'TIME'});
my $dstring = sprintf("%d/%d/%04d", $when[3], $when[4] + 1,
$when[5] + 1900);
my $tstring = sprintf("%d:%02d:%02d", $when[2], $when[1], $when[0]);
printf(OUT "%d\|%s\|%s\|%s\|%s\|%s\n", $refid, $dstring, $tstring,
$details->{'NAME'}, $amt, $details->{'REASON'});
close(OUT) and flock(OUT, 8);


print header();
print $body;
exit;
}

# '400' is an outright failure. The message got to the bank and the bank
# said no (insufficient funding, stolen card etc).
elsif ($code eq "400") {
open HTML, "<$fail_template" or weberror("Failed to open ".
"$fail_template: $!");
my $body = join("", <HTML>);
close(HTML);

$body =~ s/REFERENCENUMBER/$refid/g;
$body =~ s/RETURNMESSAGE/$msg/g;
$body =~ s/RETURNCODE/$code/g;
$body =~ s/UNPROCESSED/$unparsed/g;

print header();
print $body;
exit;
}

# Anything else isn't likely to occur, but it might. Server timeouts
# and miscellaneous network failures fall into this category.
else {
open HTML, "<$other_template" or weberror("Failed to open ".
"$other_template: $!");
my $body = join("", <HTML>);
close(HTML);

$body =~ s/REFERENCENUMBER/$refid/g;
$body =~ s/RETURNMESSAGE/$msg/g;
$body =~ s/RETURNCODE/$code/g;

print header();
print $body;
exit;
}
}


#-----------------------------------------------------------------------#
# get_details: Retrieves the transaction details of a given reference #
# number from the transaction log. #
# params: (int) refid #
# returns: (hashref) $details #
#-----------------------------------------------------------------------#
sub get_details {
my ($refid) = @_;
my %details;
my $now = time();
my @lines;

# Read in the old log and skip any lines that are more than 1 day old.
# If the line has a matching transaction number then grab the details.
open IN, "+<$translog" or weberror("Failed to open $translog: $!");
flock(IN, 2);
while (my $line = <IN>) {
chomp($line);
my @thisline = split(/\|/, $line);
next if ($now - $thisline[0] > 86400);
if ($thisline[1] == $refid) {
$details{'NAME'} = $thisline[2];
$details{'AMOUNT'} = $thisline[3];
$details{'REFID'} = $refid;
$details{'REASON'} = $thisline[4];
$details{'TIME'} = $thisline[0];
}
else {
push(@lines, $line);
}
}

# Overwrite the log with the up to date entries.
seek(IN, 0, 0);
print IN join("\n", @lines);
truncate(IN, tell(IN));
close(IN) and flock(IN, 8);
return(\%details);
}



#-----------------------------------------------------------------------#
# weberror: Prints a web page displaying an error message to the #
# browse. #
# params: (string) msg #
# returns: <exit> #
#-----------------------------------------------------------------------#
sub weberror {
my ($msg) = @_;

if (!defined($msg)) {
$msg = "An unidentified error has occurred";
}

open HTML, "<$error_template" or die("Failed to open $error_template: ".
"$!. Actual error was $msg");
my $body = join("", <HTML>);
close(HTML);

$body =~ s/ERRORMESSAGE/$msg/g;

print header();
print $body;
exit;
}