#!/usr/bin/perl -wT
use strict;
use CGI;
use DB_File;
use POSIX qw(strftime);
use Digest::HMAC_MD5 qw(hmac_md5 hmac_md5_hex);

my $q = CGI->new;

#============================================================
#basic definitions used in the ctr package                  =
#============================================================

$ENV{PATH} = "/bin:/usr/sbin";

#parameter for sending Emails
my $sendmail = "/usr/sbin/sendmail -t"; 
my $replyto  = "Reply-to: donotreply".'@'."clxbs.com\n"; 
my $from = "From: Complex Biosystems Inc <donotreply".'@'."clxbs.com>\n";
my $subject  = "Subject: Contractor registration request\n"; 
my $sendto = "To: jbeaumont".'@'."clxbs.com\n";
my $emailmsg;

#DB management parameters
#DB parameters
my $CTRfile = 'cbcontracts.db';
my $PWDfile = 'cbpasswd.db';
my $ACMfile = 'cbacm.db';

our (%ctrid,  $ctrval);
our (%acmid,  $acmval);
our (%invcid, $invcval);
our (%ctrhash, %acmhash, %pwdhash, %invchash);
our (@ctrcheck, @acmcheck, @sacmcheck, @invccheck, @keyval, $word);
our ($nacm, @acmanagers);
our ($i, $wno, $msg, $tag, $logname, $passwd, $confirm);


my @ctrkeyw = qw(bname address city state zip web invoice description acmlist);
my @ctrreqr = (1, 1, 1, 1, 1, 1, 1, 1, 0);
my @acmkeyw = qw(fname mi lname email phone fax login);
my @acmreqr = (1, 0, 1, 1, 1, 0, 1);
my @sacmkeyw = qw(fname mi lname email phone fax login blogin);
my @sacmreqr = (1, 0, 1, 1, 1, 0, 1, 1);
my @invckeyw = qw(service number frsp mrsp lrsp emailrsp phonersp 
					facr macr lacr emailacr phoneacr compl due amount status view 
					outline detail);
my @invcreqr = (1, 1,    1, 0, 1, 1, 0,   1, 0, 1, 1, 0,  1, 1, 1, 1, 1, 1, 1);

our ($bname, $address, $city, $state, $zip, $web, $invoice, $description, $acmlist);
our ($fname, $mi, $lname, $email, $phone, $fax, $login, $blogin);
our ($service, $number, $frsp, $mrsp, $lrsp, $emailrsp, $phonersp, 
		$facr, $macr, $lacr, $emailacr, $phoneacr, $compl, $due, $amount, $status, $view, 
		$outline, $detail);
our ($key, $value,  %keyval);

#Parameter shared among forms
my %bgcolor;
my %bginit = (
	ctrname =>    	'white',
	ctraddress => 	'white',
	ctrcity =>    	'white',
	ctrstate =>   	'white',
	ctrzip =>     	'white',
	ctrweb =>     	'white',
	ctrdesc =>    	'white',
	pfname =>  		'white',
	pmi =>     		'white',
	plname =>  		'white',
	pemail =>  		'white',
	pphone =>  		'white',
	pfax =>    		'white',
	plogin =>  		'white',
	ppasswd => 		'white',
	sfname => 		'white',
	smi => 			'white',
	slname => 		'white',
	semail => 		'white',
	sphone => 		'white',
	sfax => 		'white',
	slogin => 		'white',
	spasswd =>  	'white',
	scfirmp => 		'white',
	);

my %bgsubmit = (
	ctrname =>    	'white',
	ctraddress => 	'white',
	ctrcity =>    	'white',
	ctrstate =>   	'white',
	ctrzip =>     	'white',
	ctrweb =>     	'white',
	ctrdesc =>    	'white',
	pfname =>  		'white',
	pmi =>     'gray',
	plname =>  'white',
	pemail =>  'white',
	pphone =>  'white',
	pfax =>    'gray',
	plogin =>  'white',
	ppasswd => 'gray',
	sfname => 'gray',
	smi => 'gray',
	slname => 'gray',
	semail => 'gray',
	sphone => 'gray',
	sfax => 'gray',
	slogin => 'gray',
	spasswd =>  'gray',
	scfirmp => 'gray',
	);

my %bgretrieve = (
	ctrname =>    'gray',
	ctraddress => 'gray',
	ctrcity =>    'gray',
	ctrstate =>   'gray',
	ctrzip =>     'gray',
	ctrweb =>     'gray',
	ctrdesc =>    'gray',
	pfname =>  'gray',
	pmi =>     'gray',
	plname =>  'gray',
	pemail =>  'gray',
	pphone =>  'gray',
	pfax =>    'gray',
	plogin =>  'white',
	ppasswd => 'white',
	sfname => 	'gray',
	smi => 		'gray',
	slname => 	'gray',
	semail => 	'gray',
	sphone => 	'gray',
	sfax => 	'gray',
	slogin => 	'gray',
	spasswd =>  'gray',
	scfirmp => 	'gray',
	);
	
my %bgupdate = (
	ctrname =>    'white',
	ctraddress => 'white',
	ctrcity =>    'white',
	ctrstate =>   'white',
	ctrzip =>     'white',
	ctrweb =>     'white',
	ctrdesc =>    'white',
	pfname =>  'white',
	pmi =>     'gray',
	plname =>  'white',
	pemail =>  'white',
	pphone =>  'white',
	pfax =>    'gray',
	plogin =>  'gray',
	ppasswd => 'white',
	sfname => 	'white',
	smi => 	  	'white',
	slname => 	'white',
	semail => 	'white',
	sphone => 	'white',
	sfax => 	'gray',
	slogin => 	'gray',
	spasswd =>  'white',
	scfirmp => 	'white',
	);

	
#--------------- Methods -------------------------------

sub stripstring
	{
	my $trim = $_[0];
	$trim =~ s/^\s+//;   #left trailing space
	$trim =~ s/\s+$//;   #right trailing space
	#$trim =~ s/\\|\R//g; #remove carriage return
    return $trim;
	}

#-------------------------------------------------------

#============================================================
#end basic definitions used in the ctr package              =
#============================================================

my $acmname;
my @trinvc;
my $row;
my $error;

my @word;
my $btnpress = '';
my $toggleview = -1;
my $blabel;
my @invclist; #List of invoice number in the payment forms
my $ninvc;	  #numper of invoices in the payment form
my $invcdesc; #invoice description on authorize.net
my $total;    #total amount to pay 
my @trpay;    #table rows of payment form



#================================================================
#parameter of the transaction sent to the Authorize.net server  =
#================================================================
my $loginID			= "3B9dj5K2";
my $transactionKey 	= "9R8q8ZM6Q35kFfwW";
my $testMode		= "false";

#my $TransactUrl	= "https://test.authorize.net/gateway/transact.dll";
my $TransactUrl	= "https://secure.authorize.net/gateway/transact.dll";
#my $TransactUrl	= "http://www.clxbs.com/redirect.pl";

my $invcno;
my $sequence;
my $timeStamp;
my $fingerprint;

#===================================
#end parameter of the transaction  =
#===================================

#get which button been pressed
if($q->param('bsubmit'))
	{
	@word = split (" ", $q->param('bsubmit'));
	$btnpress = $word[0];
	}

if($q->param('viewinvc'))
	{
	$toggleview = $q->param('viewinvc');
	$btnpress = 'View';
	}

#print header
print $q->header;
print $q->start_html(-title=>'clxbs --graphic and simulation software for complex biological systems',
	-style=>{src=>'./smallsite.css', type=>'text/css'});

#main body division, includes banner and navigation
print '<div id="Body">';

#display the banner
print <<HTML;	
<div id="Logo"> <!--Banner-->
<IMG src="../Figures/EmbryoDigital.png" alt="Emblem" width="120" height="118" align="left" border="0">
</div>
<div id="Banner">
<p>Complex Biosystems Inc.</p>
</div>
<div id="Icon">
<IMG src="../Figures/StatueLiberty.png" alt="New York" width="80" height="118" align="right" border="0">
</div> <!--End Banner-->
HTML

#==========================================================
#Process data passed by a POST                            =
#==========================================================

#Initialize the error message
$error = '';

#Treat login, check login exists, retrieve password and check it match
if(($q->param) && ($btnpress eq 'Login'))
#if(!$q->param)
	{
	#open the password contractor and account manager DBs
	tie %pwdhash, 'DB_File', $PWDfile, O_RDWR|O_CREAT, 0644, $DB_HASH or 
		die "\n\tCannot open password DB <<$PWDfile>> \n\n"; 
	tie %ctrhash, 'DB_File', $CTRfile, O_RDWR|O_CREAT, 0644, $DB_HASH or 
		die "\n\tCannot open contractor DB <<$CTRfile>> \n\n"; 
	tie %acmhash, 'DB_File', $ACMfile, O_RDWR|O_CREAT, 0644, $DB_HASH or 
		die "\n\tCannot open account manager DB <<$ACMfile>> \n\n"; 
	
	#check the login id exists in pass word file
	$passwd = $q->param('passwd');
	$logname = stripstring($q->param('login'));
	if(!$pwdhash{$logname})
		{
		$error = "Error: the login name --$logname-- does not exist";
		$logname = '';
		goto ENDINVOICE;
		}

	#check the login id exists in account manager file file
	if(!$acmhash{$logname})
		{
		$error = "Error: the login name --$logname-- does not exist";
		$logname = '';
		goto ENDINVOICE;
		}

	#Verify the passwords match
	if($pwdhash{$logname} ne $q->param('passwd'))
		{
		$error = "Error: incorrect password for --$logname--";
		$logname = '';
		goto ENDINVOICE;
		}
	
	#get the associated contractor through blogin in acm record
	($fname, $mi, $lname, $email, $phone, $fax, $blogin) = 
		split(/<!>/, $acmhash{$logname});
	if(!$ctrhash{$blogin})
		{
		$error = "Error: account manager --$logname-- is not associated to any contractor";
		$logname = '';
		goto ENDINVOICE;
		}

	#retrieve and parse the associated contractor record
	($bname, $address, $city, $state, $web, $description, $acmlist) = 
		split(/<!>/, $ctrhash{$blogin});

	
	#contractor name and contractor login
	$acmname = "$fname $mi $lname";	
	
	#these parameter are used immediately in display
	$q->param('logname', $logname);
	$q->param('acmname', $acmname);
	$q->param('bname',   $bname);
	$q->param('blogin',  $blogin);
	
	$error = '';
	ENDINVOICE:
	untie %pwdhash;
	untie %ctrhash;
	untie %acmhash;
	}
	
#generate the invoice table
if(($q->param) && ($q->param('logname') ne '') && ($btnpress eq 'Login') || 
	($btnpress eq 'View'))
	{
	#open the contractor DB
	#and parse the field stream
	tie %ctrhash, 'DB_File', $CTRfile, O_RDWR|O_CREAT, 0644, $DB_HASH or 
		die "Cannot open the contractors DB $CTRfile \n"; 
	
	($bname, $address, $city, $state, $zip, $web, $invoice,
		$description, $acmlist) = split(/<!>/, $ctrhash{$q->param('blogin')});
	
	#Open the data base invoice
	tie %invchash, 'DB_File', $invoice, O_RDWR|O_CREAT, 0644, $DB_HASH or 
		die "Cannot open the contractor invoice DB $invoice  \n"; 
	
	#loop on the invoice records 
	$row = 0;
	while(($key, $value) = each %invchash)
		{
		#strip the field stream
		($service, $number, $frsp, $mrsp, $lrsp, $emailrsp, $phonersp, 
			$facr, $macr, $lacr, $emailacr, $phoneacr, $compl, $due, $amount, $status, $view, 
			$outline, $detail) = split(/<!>/, $value);
			
		if($number eq $toggleview)
			{
			$view = $view eq 'closed' ? 'open' : 'closed';
			}
		$blabel = $view eq 'closed' ? 'expand' : 'collapse';
		
		$trinvc[$row++] = $q->Tr({-style=>"text-align:left;"},
			"<td style=\"width:8em;\">  
				<input type=\"checkbox\" name=\"selinvoices\" value=$number>
				$number
				</input>
			</td>",	
			$q->td($outline),
			$q->td({-style => "width:6em;"}, $amount),
			$q->td({-style => "width:6em;"}, $due),
			$q->td({-style => "width:4em;"},
				'<button type="submit", name="viewinvc", style="width:5em;height:2em;font-size:9px", value=',
				$number,'>', $blabel, '</button>'),
			);
		
		#if this invoice is open
		if($view eq 'open')
			{
			$trinvc[$row++] = $q->Tr({-style=>"text-align:left;"},
				$q->td(" "),
				$q->td({-colspan => "2"},
				
			#=========== table expansion ===============================
			"<table border=\"2px\">
			<tr> 
				<td>Responsible</td>
				<td>$frsp $mrsp $lrsp</td>
				<td>Email: $emailrsp </td>
				<td>Phone: $phonersp </td>
			</tr>
			<tr> 
				<td>Acc. Representative</td>
				<td>$facr $macr $lacr</td>
				<td>Email: $emailacr </td>
				<td>Phone: $phoneacr </td>
			</tr>
			<tr>
				<td>Work completed: </td>
				<td> $compl </td>
				<td> </td>
				<td> Status: $status</td>
			</tr>
			<tr>
				<td colspan=4> <b>Details:</b> $detail </td>
			</tr>
			</table>"
			#===========================================================
					),
				$q->td(" "),
				);
			}
			
		#Update the invoice record if its view state changed
		if($number eq $toggleview)
			{
			$invcval = join("<!>", 
				$service, $number, $frsp, $mrsp, $lrsp, $emailrsp, $phonersp,
				$facr, $macr, $lacr, $emailacr, $phoneacr, $compl, $due, $amount,
				$status, $view, $outline, $detail);
			$invchash{$number} = $invcval;
			}
		}
		
	untie %ctrhash;
	untie %invchash;
	}
	
#Generate the payment table
elsif(($q->param) && ($q->param('logname') ne '') && ($btnpress eq 'Pay'))
	{
	#open the contractor DB and parse the field stream
	tie %ctrhash, 'DB_File', $CTRfile, O_RDWR|O_CREAT, 0644, $DB_HASH or 
		die "Cannot open the contractors DB $CTRfile \n"; 
	
	($bname, $address, $city, $state, $zip, $web, $invoice,
		$description, $acmlist) = split(/<!>/, $ctrhash{$q->param('blogin')});
	
	#open the account manager DB and parse the field stream
	tie %acmhash, 'DB_File', $ACMfile, O_RDWR|O_CREAT, 0644, $DB_HASH or 
		die "\n\tCannot open account manager DB <<$ACMfile>> \n\n"; 
	
	($fname, $mi, $lname, $email, $phone, $fax, $blogin) = 
		split(/<!>/, $acmhash{$q->param('logname')});
	
	#Open the data base invoice
	tie %invchash, 'DB_File', $invoice, O_RDWR|O_CREAT, 0644, $DB_HASH or 
		die "Cannot open the contractor invoice DB $invoice  \n"; 
	
	#grab the selected invoices in a list
	@invclist = $q->param('selinvoices');
	$ninvc    = @invclist;
	
	#generate the rows of the payment form
	#can the invoices that have been checked
	$row = 0; $total = 0.00; 
	for $i (0 ... $ninvc-1)
		{
		($service, $number, $frsp, $mrsp, $lrsp, $emailrsp, $phonersp, 
			$facr, $macr, $lacr, $emailacr, $phoneacr, $compl, $due, 
			$amount, $status, $view, $outline, 
			$detail) = split(/<!>/, $invchash{$invclist[$i]});
		
		$trpay[$row++] = $q->Tr({-style=>"text-align:left;"},
			$q->td({-style => "width:8em;"}, $invclist[$i]),
			$q->td($outline),
			$q->td({-style => "width:6em;"}, $amount));
			
		$trpay[$row++] = $q->Tr({-style=>"text-align:left;"},
			$q->td({-style => "width:8em;"}, " "),
			$q->td("<b>Detail: </b>", $detail),
			$q->td({-style => "width:6em;"}, " "));
		
		$total += $amount;
		if($i == 0)
			{
			$invcno = $invclist[$i];
			$invcdesc = $outline;
			}
		else
			{
			$invcno = $invcno.", ".$invclist[$i];
			$invcdesc = $invcdesc.". --- ".$outline
			}
		}	
	
	$trpay[$row++] = $q->Tr({-style=>"text-align:left;"},
			$q->td(""),
			$q->td({-style=>"text-align:right;"}, "<b>Total:</b>"),
			$q->td($total));
	
	#close contractor and invoice DB
	untie %ctrhash;
	untie %invchash;
	
	#Set the parameters of the transaction with Authorize.net
	$sequence    = strftime "%Y%m%d%H%M%S", localtime;
	$timeStamp   = time();
	$fingerprint = hmac_md5_hex($loginID . "^" . $sequence . "^" . $timeStamp . "^" . $total . "^", $transactionKey); 
	}
	
#===============================================================
#        Display section                                       =
#===============================================================
#Navigation bar, initial state
if((!$q->param) || ($q->param('logname') eq ''))
	{
	print $q->code(
	$q->ul({-id=>'Menu'},
		$q->li({-style=>"margin-top:5px;"}, 'Contractor:'),
		$q->li($q->a({-href=>'./ctrregister-small.pl'}, 'Register')),
		$q->li({-style=>"margin-top:5px;"}, 'Account manager:'),
		$q->li($q->a({-href=>'./acmlogin-small.pl'}, 'Login')),
		$q->li({-style=>"margin-top:5px;"}, 'Return to:'),
		$q->li($q->a({-href=>'./index.shtml'}, 'Home')),
		$q->li($q->a({-href=>'./contact-small.shtml'}, 'Contact us'))));
	$logname = '';
	}

#Navigation bar, once logged
elsif($q->param('logname') ne '')
	{
	print $q->code(
	$q->ul({-id=>'Menu'},
		$q->li({-style=>"margin-top:5px;"}, 'Contractor:'),
		$q->li($q->a({-href=>'./ctrregister-small.pl'}, 'Register')),
		$q->li({-style=>"margin-top:5px;"}, 'Welcome: ', $q->param('acmname')),
		$q->li($q->a({-href=>'./acmlogin-small.pl'}, 'Logout')),
		$q->li({-style=>"margin-top:5px;"}, 'Return to:'),
		$q->li($q->a({-href=>'./index.shtml'}, 'Home')),
		$q->li($q->a({-href=>'./contact-small.shtml'}, 'Contact us'))));
	}

#main content division, after banner
print '<div id="Content-noscroll">';

#Title after the navigation bar
if(($q->param) && ($q->param('logname') ne ''))
	{
	print $q->h2({-style=>"text-align:center;"},$q->param('bname'));
	}

#Form
#Login form
if((!$q->param) || ($q->param('logname') eq ''))
	{
	print $q->start_form({
		-style => "margin: 5em 2em 2em 10em;",
		-action => 'acmlogin-small.pl',
		-method => 'POST',
		-enctype => 'application/x-www-form-urlencode',
		}),

	$q->fieldset(
	$q->ol(
		$q->li($q->label({for=>'login'}, 'Account manager login:'),
			$q->textfield(-id => 'login', -name => 'login', -size => 20, -maxlength => 60)),
		
		$q->li($q->label({for=>'passwd'}, 'Password:'),
			$q->password_field(-id => 'passwd', -name => 'passwd', -size => 12, -maxlength => 24)),
		)), #end ordered list and field set

	$q->fieldset({-style=>"width:40em;", -class=>'control'},
		$q->submit('bsubmit', 'Login')),	
	$q->end_form;
	
	#display error message if there is
	if($error ne '') {print $q->h5({-style=>"color:red;"}, $error);}
	}

#generate the invoice list form
elsif(($q->param('logname') ne '') && (($btnpress eq 'Login') || 
	($btnpress eq 'View') ))
	{
	#generate the form
	print $q->start_form({
		-style   => "margin:10px 2px 2px 0px;",
		-action  => 'acmlogin-small.pl',
		-method  => 'POST',
		-enctype => 'application/x-www-form-urlencode',
		}),
	
	#include the invoice list in the form
	$q->table({-style=>"width:90%;", -align=>"center"},
		$q->Tr({-style=>"text-align:left;"},
			$q->th(" "),
			$q->th("Description"),
			$q->th("Amount"),
			$q->th("Due date"),
			$q->th(" ")),
		@trinvc),
	
	#Save in the CGI: login name, acm id business name and its login
	$q->hidden('logname', $q->param('logname')),
	$q->hidden('acmname', $q->param('acmname')),
	$q->hidden('bname',   $q->param('bname')),
	$q->hidden('blogin',  $q->param('blogin')),
	
	$q->fieldset({-style=>"width:1200px;", -class=>'control'},
		$q->submit('bsubmit', 'Pay invoices')),
	$q->end_form;
	
	#display error message if there is
	if($error ne '') {print $q->h5({-style=>"color:red;"}, $error);}
	}

#display the invoice payment form
elsif(($q->param) && ($q->param('logname') ne '') && ($btnpress eq 'Pay') )
#if(!$q->param)
	{
	#grab the selected invoices in a list
	#print("\n\n");
	
	print $q->start_form({
		-style   => "margin: 10px 2px 2px 0px;",
		-action  => $TransactUrl,
		-method  => 'POST',
		-enctype => 'application/x-www-form-urlencode',
		}),
	
	#include the invoice list in the form
	$q->table({-style=>"width:90%;", -align=>"center"},
		$q->Tr({-style=>"text-align:left;"},
			$q->th({-style => "width:8em;"}, " "),
			$q->th("Description"),
			$q->th({-style => "width:6em;"}, "Amount")),
		@trpay),
	
	#fields passed to authorize.net
	#Required fields
	$q->hidden(-name=>'x_login', -value=>$loginID),
	$q->hidden(-name=>'x_type', -value=>'AUTH_CAPTURE'),
	$q->hidden(-name=>'x_amount', -value=>$total),
	$q->hidden(-name=>'x_description', -value=>$invcdesc),
	$q->hidden(-name=>'x_invoice_num', -value=>$invcno),
	$q->hidden(-name=>'x_fp_sequence', -value=>$sequence),
	$q->hidden(-name=>'x_fp_timestamp', -value=>$timeStamp),
	$q->hidden(-name=>'x_fp_hash', -value=>$fingerprint),
	$q->hidden(-name=>'x_test_request', -value=>$testMode),
	$q->hidden(-name=>'x_show_form', -value=>'PAYMENT_FORM'),

	#fields displayed in the Authorize.net payment form
	$q->hidden(-name=>'x_version', -value=>'3.1'),
	$q->hidden(-name=>'x_first_name', -value=>$fname),
	$q->hidden(-name=>'x_last_name', -value=>$lname),
	$q->hidden(-name=>'x_company', -value=>$bname),
	$q->hidden(-name=>'x_address', -value=>$address),
	$q->hidden(-name=>'x_city', -value=>$city),
	$q->hidden(-name=>'x_state', -value=>$state),
	$q->hidden(-name=>'x_zip', -value=>$zip),
	$q->hidden(-name=>'x_country', -value=>"United States"),
	$q->hidden(-name=>'x_email', -value=>$email),
	$q->hidden(-name=>'x_phone', -value=>$phone),
	$q->hidden(-name=>'x_fax', -value=>$fax),

	#field to handle processing after submit
# 	$q->hidden(-name=>'x_relay_response', -value=>'true'),
# 	$q->hidden(-name=>'x_relay_always', -value=>'true'),
# 	$q->hidden(-name=>'x_relay_url', -value=>'http://www.clxbs.com/receipt.pl'),
	
	$q->fieldset({-style=>"width:1200px;", -class=>'control'},
		$q->submit('bsubmit', 'Proceed to payment')),
	$q->end_form;
	}

#end of HTML code
print '</div> </div>'; #end body and content divisions	
print $q->end_html;
