#!/usr/bin/perl5.003 $ConfigFile="boutique.cfg"; ############################################################################## # Notice # ------ # This software is proprietary and may not be modified, copied, # or reproduced in any manner without the expressed witten permission # of Virtual Publisher, Inc. This software is distributed under a site # license that permits it's use on a single domain/web site. # The complete source code license agreement that accompanies this # software is made a part of this software as if written herein. # # # File: boutique.cgi # # Auth: Virtual Publisher, Inc., Copyright 1996, 1997 All Rights Reserved # Website-http://virtualpublisher.com # Version: 3.0 # Release: September 21, 1997 # # # Desc: Boutique Shopping Script # # This script works with both the "GET" and "POST" CGI # methods and is compatible with both Perl 4 and Perl 5. # ################################################################ ##### # Modified: 05/08/97 # M.H.A. # Modified: 10/18/97 # 1. rename shoppro.lock to boutique.lock ################################################################# require "customshipping.pl"; ################################################################# # DEBUG FEATURES ################################################################# $ProgramName = "Boutique"; # If DEBUG is ON the Logger sub will produce output in the LogFile #$DEBUG = "ON"; $DEBUG = "OFF"; @ReservedParamNames = ( 'Prevpage', 'Template', 'Address', 'Address2', 'Subject', 'Confpage', 'ThankYouPage', 'CashRegister', 'Minpurchase', 'Minqty', 'Discount', 'FromAddress', 'Operation', 'MasterCdDb', 'dbDir', 'IndexHtmlDb' ); # added Department, Size, Weight @ProductInfoParamNames = ( 'Prodno', 'Qty', 'Price', 'Item', 'Describe', 'Info', 'Amount', 'Department', 'Size', 'Weight', ); # added Total_Items and Total_Weight @SummaryInfoParamNames = ( 'SubTotal', 'Taxes', 'Tax', 'Shipping', 'FShipping', 'Pshipping', 'Cshipping', 'Total', 'SubTotalAfterDiscount', 'DiscountAmount', 'TotalItems', 'TotalWeight' ); # added DepartmentName and DepartmentSubTotal @DepartmentSubTotalInfoParamNames = ( 'DepartmentName' ); # required elements at Shopping @RequiredElements = (); # required elements at card payment @CardElements = (); # array for holding order records @Order = (); # hashtable for Taxes: # in boutique* : key= taxtable # # format: key = value for boutique* # and vendorId.key = value for shopmall %TaxTable = (); #V ReadParametersFromFile . . . . . if true forces cgi params read from file #V SaveParametersToFile . . . . . . . . . . if true dumps cgi params to file $ReadParametersFromFile = 0; $SaveParametersToFile = 0; $ParameterFileName = "param.txt"; #S Error Messages . . . . . . . . . . . . . . . . .error messages defintions ## # $ErrMsg{'Sys_Open_File'} = "Error opening file <%PlaceHolder%>"; $ErrMsg{'Sys_Open_ConfigFile'} = "Could not open configuration file: <%PlaceHolder%>"; $ErrMsg{'Sys_Open_TemplateFile'} = "Error opening template file: <%PlaceHolder%>"; $ErrMsg{'Sys_Open_LogFile'} = "Could not open log file: <%PlaceHolder%>"; $ErrMsg{'Sys_Open_MasterFile'} = "Could not open master file: <%PlaceHolder%>"; $ErrMsg{'Sys_Open_IndexFile'} = "Could not open index file: <%PlaceHolder%>"; $ErrMsg{'Sys_Open_OrderFile'} = "Could not open order number file: <%PlaceHolder%>"; $ErrMsg{'Sys_Append_MasterFile'} = "Could not open for append master file: <%PlaceHolder%>"; $ErrMsg{'Parameters_NoParameters'} = "No CGI parameters passed to <%PlaceHolder%>"; $ErrMsg{'Sys_No_Param'} = "No CGI parameters passed to <%PlaceHolder%>"; $ErrMsg{'Sys_Missing_ConfigFile'} = "Missing ConfigFile parameter"; $ErrMsg{'User_Blank_Elem'} = "Please input value at field: <%PlaceHolder%>"; $ErrMsg{'User_Blank_Card'} = "Please input the information needed concerning your Credit Card, at field: <%PlaceHolder%>"; $ErrMsg{'User_No_Order'} = "No products were ordered"; #V DefaultErrorPage. . . display this page if no other page could be read in ## # $DefaultErrorPage = "\n" . "\n" . "An error has occured\n" . "\n" . "\n" . "\n" . "

An error has occured.

\n" . "\n" . "

Tech support could not be notified!

\n" . "
\n" . "\n" . "\n" . "\n"; ######################################################################## # PROGRAM BODY # ######################################################################## &main(); exit( 0 ); ######################################################################### # ERROR HANDLING # ######################################################################### #F UserMessage( message ) . . . . . . . . . . . . . . . . .display a message ## # sub UserMessage { local( $errorId, $errorMessage, $notificationFailed ) = @_; local( $htmlFile ); local( $message ); local( $anchor ); local( $html ); # read the current HTML file and insert the message if ( $notificationFailed == 2 ) { $htmlFile = $conf{'ERROR_PAGE.CriticalErrorPage'}; } elsif ( $notificationFailed == 1 ) { $htmlFile = $conf{'ERROR_PAGE.ErrorPage'}; } else { $htmlFile = $conf{'ERROR_PAGE.UserErrorPage'}; } if ( open( HTMLH, $htmlFile ) ) { $html = join( '', ); close( HTMLH ); } else { $html = $DefaultErrorPage; } $anchor = ""; if ( $notificationFailed eq 0 ) { $message = "

$errorMessage

\n"; } else { $message = "

The encountered error was:
\n" . "$errorMessage

\n"; } $html =~ s/$anchor/$anchor\n$message/; print "Content-type: text/html\n\n"; print $html; } #F ErrorMail( errorId, optional_param). . . . . . . . mails an error message ## # sub ErrorMail { local( $errorId, $errorMessage ) = @_; local( $errorStr ); # return if the tech support address is undefined if ( ! $conf{'TECH_SUPPORT.Address'} ) { return 0; } $errorStr = "$conf{'GENERAL_INFORMATION.ProgramName'} encountered" . " the following error:\n\n"; $errorStr .= $errorMessage; $conf{'TECH_SUPPORT.FromAddress'} =~ s/\n//; if (!$conf{'TECH_SUPPORT.FromAddress'}) { $conf{'TECH_SUPPORT.FromAddress'} = $SystemName; } if (!$conf{'TECH_SUPPORT.Subject'}) { $conf{'TECH_SUPPORT.Subject'} = "$SystemName Error"; } if ( ! open( MAILH, "| $conf{'GENERAL_INFORMATION.Sendmail'} $conf{'TECH_SUPPORT.Address'}" ) ) { return 0; } print MAILH "From: $conf{'TECH_SUPPORT.FromAddress'}\n"; print MAILH "Subject: $conf{'TECH_SUPPORT.Subject'}\n\n"; print MAILH "$errorStr\n"; close( MAILH ); return 1; } #F Error( errorId, optional_param). . . . . . . . . . . . . . .error handler ## ## ARGUMENTS ## errorId : error identification ## ## REMARKS ## This function is called in case of system errors. # sub Error { local( $errorId, $filename ) = @_; local( $errorMessage ); local( $notificationFailed ); # compose the error message $notificationFailed = 0; # if it is a system error mail to the administrator if ( $errorId =~ /Sys_/ ) { $errorMessage = "Error Id: $errorId ($ErrMsg{$errorId})\n"; $errorMessage =~ s/<%PlaceHolder%>/${filename}/; if ( ! &ErrorMail( $errorId, $errorMessage ) ) { $notificationFailed = 2; } else { $notificationFailed = 1; } } else { $errorMessage = "$ErrMsg{$errorId}\n"; $errorMessage =~ s/<%PlaceHolder%>/$filename/; } # write a message for the user &UserMessage( $errorId, $errorMessage, $notificationFailed ); exit( 1 ); } ######################################################################### # CGI PARAM HANDLING # ######################################################################### #F ReadParse(in) . . . . . . . . . . . . . read the CGI parameters into 'in' ## ## ARGUMENTS ## inHash : hash array, will contain the read in (name,value) pairs ## inArray : array, will contain the read in pairs as 'name=value' strings ## ## DESCRIPTION ## Reads in GET or POST data, converts it to unescaped text, and puts ## one key=value in each member of the list "@inArray". ## Also creates key/value pairs in %inHash, using '\0' to separate multiple ## selections. ## ## NOTE ## The function was adapted from Steven Brenner's "ReadParse" function ## in his "cgi-lib.pl" library. ## Copyright (c) 1995 Steven E. Brenner ## Unpublished work. ## Permission granted to use and modify this library so long as the ## copyright above is maintained, modifications are documented, and ## credit is given for any use of the library. # sub ReadParse { local ( *in ) = @_ if @_; local ( $i, $key, $val, $in ); # Read in text if ($ENV{'REQUEST_METHOD'} eq "GET") { $in = $ENV{'QUERY_STRING'}; } elsif ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN,$in,$ENV{'CONTENT_LENGTH'}); } @in = split(/[&;]/,$in); foreach $i (0 .. $#in) { # Convert plus's to spaces $in[$i] =~ s/\+/ /g; # Split into key and value. # splits on the first =. ($key, $val) = split(/=/,$in[$i],2); # Convert %XX from hex numbers to alphanumeric $key =~ s/%(..)/pack("c",hex($1))/ge; $val =~ s/%(..)/pack("c",hex($1))/ge; # Associate key and value $in{$key} .= "\0" if (defined($in{$key})); # \0 is the multiple separator $in{$key} .= $val; } return scalar(@in); } #F WriteParamsToFile(fileName,params). . . . . . .write the params to a file ## ## ARGUMENTS ## fileName: the file name of the file used for writing the parameters ## params : the parameters # sub WriteParamsToFile { local( $fileName, *paramsHash, *paramsArray ) = @_; local( $keys, $values, $total ); local( $separator1, $separator2 ); local( $paramName, $paramValue ); local( $i ); $separator1 = qq(--sepa1--); $separator2 = qq(--sepa2--); if ( !open( FILEHANDLE, ">${fileName}" ) ) { &Error( 'Sys_Open_File', $fileName ); return 0; } $keys = ""; $values = ""; foreach $i ( 0 .. $#paramsArray-1 ) { ( $paramName, $paramValue ) = split( /=/, $paramsArray[ $i ], 2 ); $keys .= $paramName . $separator1; $values .= $paramValue . $separator1; } ( $paramName, $paramValue ) = split( /=/, $paramsArray[ $#paramsArray ], 2 ); $keys .= $paramName; $values .= $paramValue; $total = $keys . $separator2 . $values; print FILEHANDLE $total; close( FILEHANDLE ); # `chmod 666 $fileName`; } #F ReadParamsFromFile(fileName, params). . . . . . . . read params from file ## ## ARGUMENTS ## fileName: the file name of the file used for writing the parameters ## params : the parameters # sub ReadParamsFromFile { local( $fileName, *paramsHash, *paramsArray ) = @_; local( $keys, $values, $total ); local( $content ); local( $separator1, $separator2 ); $separator1 = qq(--sepa1--); $separator2 = qq(--sepa2--); #get the file content open( FILEHANDLE, $fileName ) || &Error( 'Sys_Open_File',$fileName ); $content = join( "", ); close( FILEHANDLE ); #get the keys and the values ( $keys, $values ) = split( $separator2, $content ); @keys = split( $separator1, $keys ); @values = split( $separator1, $values ); #setup the params hash while( @keys ) { $key = shift( @keys ); $value = shift( @values ); $paramsHash{$key} = $value; push( @paramsArray, "$key=$value" ); } return 1; } # #F ReadCgiParameters . . . . . . . . . . . read the CGI parameters into 'in' ## ## PARAMETERS ## in: hash array, will contain the read in (name,value) pairs ## ## DESCRIPTION ## ## # sub ReadCgiParameters { local( *inHash, *inArray ) = @_; if( $SaveParametersToFile == 1 ) { print "Content-type: text/plain\n\n"; if ( !&ReadParse ) { &Error( 'Sys_No_Param', "boutique.cgi" ); return 0; } &WriteParamsToFile( $ParameterFileName, *inHash, *inArray ); exit; } if( $ReadParametersFromFile == 1 ) { return &ReadParamsFromFile( $ParameterFileName, *inHash, *inArray ); } else { if ( ! &ReadParse( *inHash, *inArray ) ) { &Error( 'Sys_No_Param', "boutique.cgi" ); return 0; } return 1; } } ########################################################################## # CONFIG FILE HANDLING # ########################################################################## #F ReadConfigFile(fileName,conf). . . . . . . process the configuration file ## ## Reads from configuration file and outputs ## %conf , containing ($name, $value) pairs. ## sub ReadConfigFile { local( $fileName, *conf ) = @_; local( $section) = ""; local( $name) = ""; local( $value) = ""; local( $flagmulti) = 0; local( $flagsection) = 1; # open configuration file if ( ! open( CONFIG_FILE, "<$fileName" ) ) { &Error( 'Sys_Open_ConfigFile', $fileName ); return 0; } # parse configuration file READ_LABEL: while ( ) { # ignore empty line if (/^\n$/) { next READ_LABEL; } # ignore comments if (/^[#;].*$/) { next READ_LABEL; } # encounter section if ( /^\[(.*)\]$/ ) { if ( $flagmulti ) { %conf = (%conf, $name, $value); } $flagsection = 0; $flagmulti = 1; $section = $1; $value = ''; # add section information %conf = (%conf, $section, 'true' ); next READ_LABEL; } # name = value if ( /\s*(\S+)\s*=\s*([^\n]*)/ ) { if ( $flagmulti && $flagsection ) { %conf = (%conf, $name, $value); } if ( ( defined( $section ) ) && ( $section ne "" ) ) { $name =$section . "."; } $name .= $1; $value = $2; $flagsection = 1; next READ_LABEL; } # if none of the above if ( $flagmulti ) { /(.*)/; $value .= "$1\n"; } next READ_LABEL; } # this should happen if ( $flagmulti ) { %conf = (%conf, $name, $value); } close( CONFIG_FILE ); return 1; } # #F UpdateInHash(inHash,conf). . . . . . . updates the inHash table with ## values from %conf ## sub UpdateInHash { # creates the link between old and new variable names $inHash{'Taxes'} = ""; &Logger( "UpdateInHash begin..." ); # Config file values # # GENERAL_INFORMATION part $inHash{'TemplatePath'} = $conf{'GENERAL_INFORMATION.TemplatePath'}; $inHash{'HtmlUrl'} = $conf{'GENERAL_INFORMATION.HtmlUrl'}; $inHash{'Prevpage'} = $inHash{'HtmlUrl'} . "/" . $conf{'GENERAL_INFORMATION.MainProductPage'}; $inHash{'Confpage'} = $inHash{'TemplatePath'} . "/" . $conf{'GENERAL_INFORMATION.SaleslipPage'}; $inHash{'CashRegister'} = $inHash{'TemplatePath'} . "/" . $conf{'GENERAL_INFORMATION.CheckoutPage'}; $inHash{'ThankYouPage'} = $inHash{'TemplatePath'} . "/" . $conf{'GENERAL_INFORMATION.ThankYouPage'}; if ( defined( $conf{'GENERAL_INFORMATION.Frames'} ) ) { $inHash{'Frames'} = $conf{'GENERAL_INFORMATION.Frames'} } if ( (!$inHash{'NextUrl'} ) && ( $conf{'GENERAL_INFORMATION.NextUrl'} ) ) { $inHash{'NextUrl'} = $conf{'GENERAL_INFORMATION.NextUrl'}; } $inHash{'OrderNoFile'} = $conf{'GENERAL_INFORMATION.OrderNoFile'}; # VENDOR_INFORMATION part $inHash{'Address'} = $conf{'VENDOR_INFORMATION.DefaultAddress'}; $inHash{'Subject'} = $conf{'VENDOR_INFORMATION.DefaultSubject'}; $inHash{'FromAddress'} = $conf{'VENDOR_INFORMATION.DefaultFromAddress'}; $inHash{'Template'} = ""; if ( defined( $conf{'VENDOR_INFORMATION.DefaultTemplate'} ) && ( $conf{'VENDOR_INFORMATION.DefaultTemplate'} ne "" ) ) { $inHash{'Template'} = $inHash{'TemplatePath'} . "/" . $conf{'VENDOR_INFORMATION.DefaultTemplate'}; } if ( defined ( $conf{'VENDOR_INFORMATION.ForwardAddress'} ) ) { $inHash{'ForwardAddress'} = $conf{'VENDOR_INFORMATION.ForwardAddress'}; } $inHash{'ForwardTemplate'} = ""; if ( defined( $conf{'VENDOR_INFORMATION.ForwardTemplate'} ) && ( $conf{'VENDOR_INFORMATION.ForwardTemplate'} ne "" ) ) { $inHash{'ForwardTemplate'} = $inHash{'TemplatePath'} . "/" . $conf{'VENDOR_INFORMATION.ForwardTemplate'}; } # STORAGE_INFORMATION part $inHash{'TemplateDbPath'} = $conf{'STORAGE_INFORMATION.Template_db_path'}; $inHash{'TemplateDbPath'} = $conf{'STORAGE_INFORMATION.Template_db_path'}; $inHash{'dbDir'} = $conf{'STORAGE_INFORMATION.db_dir'}; $inHash{'TemplateMCdDb'} = $inHash{'TemplateDbPath'} . "/" . $conf{'STORAGE_INFORMATION.Template_m_cd_db'}; $inHash{'MasterCdDb'} = $inHash{'dbDir'} . "/" . $conf{'STORAGE_INFORMATION.Master_cd_db'}; $inHash{'IndexHtmlDb'} = $inHash{'dbDir'} ."/" .$conf{'STORAGE_INFORMATION.Index_html_db'}; $inHash{'TemplateIndexDb'} = $inHash{'TemplateDbPath'} . "/" .$conf{'STORAGE_INFORMATION.Template_index_db'}; $inHash{'TemplateMHtmlDb' } = $inHash{'TemplateDbPath'} . "/" . $conf{'STORAGE_INFORMATION.Template_m_html_db'}; # CALCULATIONS part $inHash{'Minqty'} = $conf{'CALCULATIONS.Minqty'}; $inHash{'Minpurchase'} = $conf{'CALCULATIONS.Minpurchase'}; $inHash{'Discount'} = $conf{'CALCULATIONS.Discount'}; if ( defined ( $conf{'CALCULATIONS.Fshipping'} ) ) { $inHash{'Fshipping'} = $conf{'CALCULATIONS.Fshipping'}; } if ( defined ( $conf{'CALCULATIONS.Pshipping'} ) ) { $inHash{'Pshipping'} = $conf{'CALCULATIONS.Pshipping'}; } if ( defined ( $conf{'CALCULATIONS.Cshipping'} ) ) { $inHash{'Cshipping'} = $conf{'CALCULATIONS.Cshipping'}; } } #F CreateRequiredElements ## ## DESCRIPTION ## creates the required elements for user input at saleslip.html. ## or creates the Vendors cfg files hashtable with path to *.cfg ## from shopmall.cfg VENDOR_INFORMATION. ## # sub CreateRequiredElements { local( $typeOfRequiredElements ) = @_; local( @confKeys ); local( $matchString ); local( @returnedElements ) = (); &Logger("CreateRequiredElements begin"); @confKeys = keys( %conf ); if ( $typeOfRequiredElements eq "Fields" ) { $matchString = "REQUIRED_FIELDS\."; } if ( $typeOfRequiredElements eq "Cards" ) { $matchString = "CARD_FIELDS\."; } foreach $element ( @confKeys ) { if ( $element =~ /^$matchString.*$/ ) { $element =~ s/$matchString//; push( @returnedElements, $element ); } } return @returnedElements; } #F CreateTaxTable . . . . . . .create the Taxes hashtable with ## values from %conf ## # sub CreateTaxTable { local( $key, $value ); local( @taxElements ); &Logger( "CreateTaxTable begin..." ); if ( defined( $conf{'TAX_TABLE.TaxTable'} ) ) { @taxElements = split( /;/, $conf{'TAX_TABLE.TaxTable'} ); foreach $element ( @taxElements ) { ( $key, $value ) = split( /,/, $element, 2 ); $TaxTable{$key} = $value; } } } ########################################################################## # DEBUG FEATURE # ########################################################################## ########################################################################## # This subroutine is used for error loging. # The output will be written in the TmpDir directory # ########################################################################## sub Logger { local( $message ) = @_; local( $LogFile ) = "$conf{'GENERAL_INFORMATION.TmpDir'}/boutique.log"; if ( $DEBUG eq "ON" ) { # open logger file if ( ! -e "$LogFile" ) { if ( ! open( LOG, ">$LogFile" ) ) { &Error( 'Sys_Open_LogFile', $LogFile ); return 0; } } else { if ( ! open( LOG, ">>$LogFile" ) ) { &Error( 'Sys_Open_LogFile', $LogFile ); return 0; } } print LOG $message,"\n"; close ( LOG ); } } ########################################################################## # CHECKINGS # ########################################################################## #F VerifyRequiredFields . . . . . . . . . . . . . . . .check required fields ## ## ARGUMENTS ## ## ## DESCRIPTION ## Checks to see if all the required fields are defined. If not, outputs an ## error message page. # sub VerifyRequiredFields { local( *in ) = shift; local( $key, $val, $printedHeaderFlag ); &Logger( "VerifyRequiredFFields begin..." ); $printedHeaderFlag = 0; while ( ( $key, $val ) = each(%in) ) { if ( substr( $key, 0, 2 ) eq 'R_' && $val eq '' ) { if ( ! $printedHeaderFlag ) { print <Required Fields Were Left Blank

Required Fields Were Left Blank

END $printedHeaderFlag = 1; } # The E-mail address is treated separately. # In the error message will apear "e-mail Address" # replacing the ?_Address word if ( ( $key eq 'Address' ) || ( $key eq 'R_Address' ) || ( $key eq 'Address2' ) || ( $key eq 'R_Address2' ) ) { $key = 'e-mail Address' ; } else { # Chop the leading "R_" off param names for display. # Replace any other "_" characters appearing in the # key name with " " to make the error message more # user friendly. $key = substr( $key, 2 ); $key =~ s/_/ /g; } print "
The required field '${key}' was left blank." } } if ( $printedHeaderFlag ) { print <Please press the 'BACK' button in your browser and make corrections. END &Logger( "Bad requierd fields , die" ); &Logger( "-----------------------" ); exit; } } #F VerifyEmailAddresses(adresses) . . . . check email addresses for validity ## ## ARGUMENTS ## ## ## DESCRIPTION ## Checks to see if all the addresses are corectly formatted. If not, outputs ## an error message page. # sub VerifyEmailAddresses { local( *in ) = shift; local( $validChars, $address, @addresses ); &Logger( "VerifyEmailAddresses begin..." ); push( @addresses, $in{'Address'} ) if $in{'Address'}; push( @addresses, $in{'Address2'} ) if $in{'Address2'}; push( @addresses, $in{'R_Address'} ) if $in{'R_Address'}; push( @addresses, $in{'R_Address2'} ) if $in{'R_Address2'}; push( @addresses, $in{'ForwardAddress'} ) if $in{'ForwardAddress'}; push( @addresses, $ADDRESS ) if $ADDRESS; $validChars = 'a-zA-Z0-9_%!\-'; foreach $address ( @addresses ) { if ($address && $address !~ /([\.$validChars]+\@[$validChars]+\.[\.$validChars]+)/) { print < Incorrectly Formatted E-mail Address

Incorrectly Formatted E-mail Address

The E-mail address '${address}' appears to be incorrectly formatted. If you entered this address on the previous page, please press your browsers back button to go back and fix it. Otherwise, this E-mail address is one that was hardcoded by the web page author. Please contact them and make them aware of this problem. EOF &Logger( "Bad e-mail addressess , die" ); &Logger( "-----------------------" ); exit; } # End of if the address is not null and formatted incorrectly } # End of foreach loop to iterate over all possible E-mail addresses } # End of subroutine ########################################################################## # PROGRAM PARTS # ########################################################################## ########################################################################### # Get the order ########################################################################### sub GetOrder { local( $pName, $maxIndex, $arrayName, $miniScript ); local( @qtys, @prodnos, @prices, @items, @describes, @infos, @departments, @sizes, @weights ); local( @prodIDs ); local( $i ); &Logger( "GetOrder Begin" ); # Now get order info from CGI param's $maxIndex = -1; foreach $pName ( @ProductInfoParamNames ) { $arrayName = "\L${pName}s"; $miniScript = '@'. $arrayName . ' = split(/\0/, $inHash{' . '"${pName}"}); ' . '$maxIndex = $#' . $arrayName . ' if $#' . $arrayName . ' > $maxIndex;'; eval $miniScript; } for ( $i = 0; $i <= $maxIndex; ++$i ) { if ( $qtys[$i] > 0 ) { $prodIDs[ $i ] = join( '|', $prodnos[$i], $qtys[$i], $prices[$i], $items[$i], $describes[$i], $infos[$i], $departments[$i], $sizes[$i], $weights[$i]) if ( $prodnos[$i] && $prices[$i] ); # Append this product number to our sequence-keeping # array of product numbers push( @order, $prodIDs[ $i ] ); } } &Logger( "@order" ); } # End of sub GetOrder ############################################################################ # This routine gets a new order number ############################################################################ sub NewOrderNumber { local( $orderno ); local( $fileOnError ); &Logger( "NewOrderNumber Begin" ); $fileOnError = "$conf{'GENERAL_INFORMATION.TmpDir'}"; $fileOnError .= "/"; $fileOnError .= "boutique.lock"; if ( ! open( LOCKFILE, "> $conf{'GENERAL_INFORMATION.TmpDir'}/boutique.lock" ) ) { &Error( 'Sys_Open_LockFile', $fileOnError ); return 0; } if ( ! flock( LOCKFILE , 2 ) ) { &Error( 'Sys_Open_LockFile', $fileOnError ); return 0; } seek( LOCKFILE, 0, 2 ); # Reads the orderno.txt file and increases it with one # The actual value will be saved into %in and @in if ( !open( ORDERNO, $inHash{'OrderNoFile'} ) ) { &Error( 'Sys_Open_OrderFile', $inHash{'OrderNoFile'} ); return ; } $orderno = ; close( ORDERNO ); chop $orderno; # if the feature is turned on if ( $orderno >= 0 ) { ++$orderno; } # Save new orderno value if ( !open( ORDERNO, "> $inHash{'OrderNoFile'}" ) ) { &Error( 'Sys_Open_OrderFile', $inHash{'OrderNoFile'} ); return ; } print ORDERNO $orderno,"\n"; close( ORDERNO ); # `chmod 666 $OrderNoFile`; close( LOCKFILE ); seek( LOCKFILE, 0, 2 ); return $orderno; } ############################################################################ # Given a template and an associative array of CGI parameters, this routine # will put the parameters into the appropriate places in the template and # remove any unused placeholders in the template. ############################################################################ sub FormatAccordingToTemplate { local( $template, *in ) = @_; local( $pName, $pVal ); local( $hidden ); &Logger( "FormatAccordingToTemplate Begin" ); # here we replace the parameter placeholders with the parameter values while ( ( $pName, $pVal ) = each(%in) ) { # replace occurances of '${P_NAME}' and '$P_NAME' with # the parameter's value $template =~ s/\$\{${pName}\}/${pVal}/g; $template =~ s/\$${pName}/${pVal}/g; } # get rid of any leftover parameters in the template $template =~ s/\$\{\w+\}//g; # insert the remaining parameters as hidden fields to preserve state info $hidden = ''; while ( ( $pName, $pVal ) = each(%in) ) { if ( $pName =~ /Address/ ) { $hidden .= "\n"; } else { if ( ! grep( $pName =~ $_, ( @ReservedParamNames, @ProductInfoParamNames, @SummaryInfoParamNames, @DepartmentSubTotalInfoParamNames ) ) ) { $hidden .= "\n"; } } } $template =~ s/()/$1\n$hidden/i; return $template; } ############################################################################### # This routine does some heavy derivations based on the order-related CGI # parameters. Then it calls on the "FormatAccordingToTemplate" routine # to produce output. ############################################################################### # The products are now identified via an internal product ID, so there # can coexist more then one product with the same product number # and different parameters sub FormatShoppingCartData { local( $template, *in2, $cr ) = @_; local( @template, $newTemplate ); local( $detailProductLines, $detailDepartmentLines); local( $newDetailLines ); local( @prices, @qtys, @prodnos, @items, @describes, @infos); local( @departments, @sizes, @weights, @oldqtys ); local( $maxIndex, $pName, $arrayName, $miniScript, $prodno, $restOfRec ); local( $line, $i ); local( $index1,$index2 ); local( $isDetail ) = 0; local( $anchor1 ) = "\n"; local( $anchor2 ) = "\n"; #array holding the product IDs local ( @prodIDs ); &Logger( "FormatShopCart begin with $CR" ); # This loop builds the arrays 'costs', 'qtys', 'prices', etc. $i = 0; foreach $prodID ( @order ) { $prodIDs[$i] = $prodID; ( $prodnos[$i], $qtys[$i], $prices[$i], $items[$i], $describes[$i], $infos[$i], $departments[$i], $sizes[$i], $weights[$i], $oldqtys[$i] ) = split(/\|/, $prodID); ++$i; } foreach $index1 ( @departments ) { $index2 = "Department${index1}SubTotal"; $in2{"${index2}"} = 0; } # find the number of products ordered $maxIndex = $#prodIDs; # split template into lines @template = split( /\n/, $template ); # create Template between BeginProductDetail-EndDetail # and between BeginDepartmentDetail-EndDetail $detailProductLines = ""; $detailDepartmentLines = ""; $newTemplate = ""; foreach $line ( @template ) { if ( $line =~/\n"; } if ( $line =~/\n"; } if ( $isDetail eq 0 ) { $newTemplate .= $line . "\n"; } # this is just for escaping comments like # Begin***Detail or EndDetail from newTemplate if ( $isDetail eq 3 ) { $isDetail = 0; } } # change values in selected template for ( $i = 0; $i <= $maxIndex; $i++ ) { # Only do all the following if the order quantity was > 0 # and if it is the spec. department if ( $qtys[$i] > 0 ) { $newDetailLines = $detailProductLines; foreach $pName ( @ProductInfoParamNames ) { # Numerify the detail line parameters $newDetailLines =~ s/\$\{${pName}\}/\$\{${pName}${i}\}/g; $newDetailLines =~ s/\$${pName}/\$${pName}${i}/g; # Generate a numbered parameter for this detail line parameter $miniScript = '$' . "\L${pName}s[${i}]"; #' $in2{"${pName}${i}"} = eval $miniScript; } # Insert the new set of detail lines' $newTemplate =~ s/$anchor1/$newDetailLines\n$anchor1/; # check whether the key is in 'deps' $isIn = 0; foreach $key ( @deps ) { if ( $key eq $departments[$i] ) { $isIn = 1; last; } } if ( $isIn == 0 ) { push( @deps, $departments[$i] ); } } # End of "if this qty was greater than zero" } if ( $conf{'PRODUCT_PARAMETERS.EnableDepartmentSubtotals'} eq "Y" ) { foreach $DepartmentName ( @deps ) { $newDetailLines = $detailDepartmentLines; # replace the department name tag $newDetailLines =~ s/\$\{DepartmentName\}/${DepartmentName}/g; $newDetailLines =~ s/\$DepartmentName/${DepartmentName}/g; # Insert the new set of detail lines' $newTemplate =~ s/$anchor2/$newDetailLines\n$anchor2/; } } $newTemplate =~ s/$anchor1//; $newTemplate =~ s/$anchor2//; # format data local( $format ) = ('%6.2f'); # calculate taxes &CalculateTax(); # Now generate parameters for derived values for ( $i = 0; $i <= $maxIndex; $i++ ) { $in2{"Amount${i}"} = sprintf( $format, $in2{"Amount${i}"} ); #Now generate the Department Subtotals if ( $conf{'PRODUCT_PARAMETERS.EnableDepartmentSubtotals'} eq "Y" ) { $index1 = "${departments[$i]}"; $index2 = "Department${index1}SubTotal"; $in2{"${index2}"} = sprintf( $format, $in2{"${index2}"} + $qtys[$i] * $prices [$i] ); } } $in2{'SubTotal'} = sprintf( $format, $in2{'SubTotal'} ); $in2{'SubTotalAfterDiscount'} = sprintf( $format, $in2{'SubTotalAfterDiscount'} ); $in2{'DiscountAmount'} = sprintf( $format, $in2{'DiscountAmount'} ); $in2{'Tax'} = sprintf($format, $in2{'Tax'}); $in2{'Shipping'} = sprintf( $format, $in2{'Shipping'} ); $in2{'Total'} = sprintf( $format, $in2{'Total'} ); # finally, format all this according to the template and return value return &FormatAccordingToTemplate( $newTemplate, *in2 ); } #F CalculateTax ## ## ## DESCRIPTION ## CALCULATE TAX ## Note: ## The TaxTable is defined in the configuration file # sub CalculateTax { local( $taxPercentage ); &Logger( "CalculateTax Begin" ); $in2{'SubTotal'} = 0; $in2{'TotalItems'} = 0; $in2{'TotalWeight'} = 0; $in2{'TotalQty'} = 0; for ( $i = 0; $i <= $maxIndex; $i++ ) { $in2{"Amount${i}"} = $qtys[$i] * $prices[$i]; $in2{'SubTotal'} += $qtys[$i] * $prices[$i]; $in2{'TotalQty'} += $qtys[$i]; #Newly added TotalWeight and TotalItems $in2{'TotalWeight'}+= $weights[$i]*$qtys[$i]; $in2{'TotalItems'} += $qtys[$i]; } $in2{'DiscountAmount'} = 0; # Also if "Minpurchase" dollar threshold is present and this order meets or # exceeds it, then give them the percentage discount specified in # "Discount". The discounted amount will be placed in the param named # "SubTotal_After_Discount". if ($in2{'Minpurchase'} && $in2{'SubTotal'} >= $in2{'Minpurchase'}) { $in2{'DiscountAmount'} = $in2{'SubTotal'} * $in2{'Discount'}; } else { # Likewise, if "Minqty" quantity threshold is present and this # order meets or exceeds it, then give them the percentage # discount specified in "Discount". if ($in2{'Minqty'} && $in2{'TotalQty'} >= $in2{'Minqty'}) { $in2{'DiscountAmount'} = $in2{'SubTotal'} * $in2{'Discount'}; } } $in2{'SubTotalAfterDiscount'} = $in2{'SubTotal'} - $in2{'DiscountAmount'}; $taxPercentage = ( $TaxTable{$in2{'State'}} || $in2{'Taxes'} ); # If the tax percentage is >= 1 (i.e.- 100%) then the user # must have entered their tax as a whole number rather than a fraction. $taxPercentage /= 100 if $taxPercentage >= 1; $in2{'Taxes'} = sprintf( "%0.2f", $taxPercentage ); $in2{'Tax'} = 0; $in2{'Tax'} += $taxPercentage * $in2{'SubTotalAfterDiscount'}; # Calculate shipping charges $in2{'Shipping'} = 0; # Add in any Percentage shipping charge if ( defined( $in2{'Pshipping'} ) ) { $in2{'Shipping'} = $in2{'Pshipping'} * $in2{'SubTotalAfterDiscount'}; } # Add in any Flat-rate shipping charge if ( defined( $in2{'Fshipping'} ) ) { $in2{'Shipping'} = $in2{'Fshipping'} ; } # Now call subroutine to calculate any custom shipping costs if ( defined $in2{'Cshipping'} ) { $in2{'Cshipping'} = &CalculateCustomShippingCost ( $in2{'TotalQty'}, $in2{'TotalItems'}, $in2{'TotalWeight'}, $in2{'State'}, $in2{'Country'}, $in2{'SubTotal'}, *prodnos, *qtys, $in2{'method'} ); $in2{'Shipping'} = $in2{'Cshipping'}; } # Calculate 'Total' $in2{'Total'} = 0; $in2{'Total'} += $in2{'SubTotalAfterDiscount'} + $in2{'Tax'} + $in2{'Shipping'}; } # End of subroutine 'CalculateTax' ########################################################################## # This subroutine composes the e-mail message containing the order # It returns a string containing the body of the e-mail message. ########################################################################## sub ComposeEmailBody { local( $ltemplate ) = @_; local( $body ); # the return string local( $currentNumber ); local( @deps ); &Logger( "ComposeEmailBody Begin with" ); &Logger( " $ltemplate" ); # reads the current orderno that was increased when printing the # saleslip page if ( ! open( ORDERNO, $inHash{'OrderNoFile'} ) ) { &Error( 'Sys_Open_OrderFile', $inHash{'OrderNoFile'} ); return 0; } $currentNumber = ; close( ORDERNO ); chop $currentNumber; # if the feature turned on if ( $currentNumber >= 0 ) { $inHash{'Orderno'} = $currentNumber; push( @inHash, "Orderno=${currentNumber}" ); } # if template file was specified if ($ltemplate ne "") { if ( ! open(TEMPLATEFILE, "$ltemplate") ) { &Error( 'Sys_Open_TemplateFile', $ltemplate ); return 0; } $template = join( '', ); close( TEMPLATEFILE ); } # if template file was not specified else { # define a default template and use it to format the cart data # In the header include all "general information" parameters $template = ''; # Now append the hard-coded portion of the default template $template .= <<'EOF'; Name : ${Name} Address : ${Addr} City : ${City} State : ${State} Zip Code : ${Zip} Country : ${Country} Phone Number : ${Phone} E-Mail Address : ${Address} Fax Number : ${Fax} Payment Method : ${Payment} Card : ${cardno} Exp. Date : ${expdate} Name-As on Card : ${cardname} Orderno : ${Orderno} Item: ${Prodno} - ${Item} ${Describe} - ${Info} Qty: ${Qty} at $${Price} $${Amount} Size: ${Size} Weight: ${Weight} Department: ${Department} EOF $template .= <<'EOD'; ------- Total Items : ${TotalItems} Total Weight : ${TotalWeight} Subtotal $${SubTotal} EOD #If Department subtotals are enabled then e-mail them: if ( $conf{'PRODUCT_PARAMETERS.EnableDepartmentSubtotals'} eq "Y" ) { $template .= "Department Subtotals\n\n"; $template .= "\n"; $template .= "Department \${DepartmentName} subtotal : "; $template .= "\$\${Department\${DepartmentName}SubTotal}\n"; $template .= ""; } # If we've got "Minpurchase" and "Discount" param's, then include # DiscountAmount and SubTotal_After_Discount in default template. if ( $inHash{'Minpurchase'} || $inHash{'Discount'} ) { $template .= <<'EOF'; Discount $${DiscountAmount} Subtotal after Discount $${SubTotalAfterDiscount} Tax @ ${Taxes} $${Tax} Shipping/Handling $${Shipping} ======= Total $${Total} EOF } } # format the E-mail message body according to the template $body = &FormatShoppingCartData( $template, *inHash, "\n" ); return ( $body ); } ########################################################################### # This subroutine compose a database entry according to a specified # template done as the first argument ########################################################################### sub ComposeDbBody { local( $ltemplate, $cr ) = @_; local( $body ); local( $currentNumber ); local( @deps ); &Logger( "ComposeDbBody Begin" ); # reads the current orderno that was increased when printing the # saleslip page if ( !open( ORDERNO, $inHash{'OrderNoFile'} ) ) { &Error( 'Sys_Open_OrderFile', $inHash{'OrderNoFile'} ); return 0; } $currentNumber = ; close( ORDERNO ); chop $currentNumber; # if the feature turned on if ( $currentNumber >= 0 ) { $inHash{'Orderno'} = $currentNumber; $inHash{'OrderHref'}="order.$inHash{Orderno}.master.html"; $inHash{'OrderDetailHref'}="order.$inHash{Orderno}.detail.html"; push( @inHash, "Orderno=${currentNumber}" ); } # if template file was specified if ($ltemplate ne "") { if ( !open(TEMPLATEFILE, "$ltemplate") ) { &Error( 'Sys_Open_TemplateFile', $ltemplate ); return 0; } $template = join( '', ); close( TEMPLATEFILE ); # format the E-mail message body according to the template $body = &FormatShoppingCartData( $template, *inHash, $cr ); } } #F EmailIt ## ## just call the sendmail program # sub EmailIt { local($address, $subject, $body, $from) = @_; local($validChars); &Logger( "EmailIt Begin via $conf{'GENERAL_INFORMATION.Sendmail'}" ); &Logger( "$address, $subject, $from" ); $validChars = 'a-zA-Z0-9_%!\-'; # First check the validity of the Email address if ($address =~ /([\.$validChars]+\@[$validChars]+\.[\.$validChars]+)/) { if( open(SENDMAIL, "| $conf{'GENERAL_INFORMATION.Sendmail'} ${address} >/dev/null" ) ) { print SENDMAIL "From: ${from}\n" if $from; print SENDMAIL "Reply-to: ${from}\n" if $from; print SENDMAIL "Subject: ${subject}\n\n"; print SENDMAIL $body; print SENDMAIL "\n.\n"; close(SENDMAIL); } else { warn "Could not open an output pipe to '$conf{'GENERAL_INFORMATION.Sendmail'}'." ." I will try to redirect browser to 'Prevpage' anyway."; } } else { # Bad Email address warn "Incorrectly formatted E-mail address (it was '${address}')."; } } #F SelectPageToLoad ## ## DESCRIPTION ## ## If the user chose to go to the confirmation page (really just a ## sales summary page), then print out that page with param ## substitutions. ## I've left the possibility of splitting the one product page into ## product and checkout pages. ## Otherwise, redirect them to the 'Prevpage' (i.e.- main page). # sub SelectPageToLoad { &Logger( "SelectPageToLoad Begin" ); $lastPageToLoadName = ""; if ( $inHash{'Operation'} eq "checkout" ) { $lastPageToLoadName = $inHash{'CashRegister'}; } elsif ( $inHash{'Operation'} eq 'final_confirm' ) { # check if required Fields exists foreach $element ( @RequiredElements ) { if ( (!defined( $inHash{"$element"} ) ) || ( $inHash{"$element"} eq "" ) ) { &Error( 'User_Blank_Elem', $conf{"REQUIRED_FIELDS.$element"} ); return 0; } } if( $inHash{'Payment'} ne "check" ) { foreach $element ( @CardElements ) { if ( (!defined( $inHash{"$element"} ) ) || ( $inHash{"$element"} eq "" ) ) { &Error( 'User_Blank_Card', $conf{"CARD_FIELDS.$element"} ); return 0; } } } # this is the saleslip page $lastPageToLoadName = $inHash{'Confpage'}; } elsif ( ( $inHash{'Operation'} eq 'thank-you' ) || ( $inHash{'Operation'} eq 'saleslip' ) ) { if ( (!defined( $inHash{'Qty'} ) ) || ( $inHash{'Qty'} eq "" ) ) { &Error('User_No_Order', "" ); return 0; } $orderno = &NewOrderNumber(); # if the feature is turned on if ( $orderno >= 0 ) { $inHash{'Orderno'} = $orderno; push( @inHash, "Orderno=${orderno}" ); } # this is the saleslip page $lastPageToLoadName = $inHash{'ThankYouPage'}; } &Logger( " lastPageToLoadName: $lastPageToLoadName" ); return $lastPageToLoadName; } #F RedirectBrowser ## ## DESCRIPTION ## ## Redirect browser if URL was specified. Otherwise print a warning. ## If NextUrl specified, then use it instead of Prevpage # # sub RedirectBrowser { &Logger( "RedirectBrowser Begin" ); if ( ( $inHash{'NextUrl'} ) && ( $inHash{'Operation'} eq 'saleslip' ) ) { $url = $inHash{'NextUrl'}; print "Status: 302 Found\r\nLocation: ${url}\r\nURI:". " <${url}>\r\nContent-type: text/html\r\n\r\n"; &Logger( " RedirectBrowser NextUrl: $url" ); } else { if ( defined ( $inHash{'Prevpage'} ) ) { $url = $inHash{'Prevpage'}; print "Status: 302 Found\r\nLocation: ${url}\r\nURI:". " <${url}>\r\nContent-type: text/html\r\n\r\n"; &Logger( " RedirectBrowser Prevpage: $url" ); } } } #F UpdateCommaDataBase ## ## DESCRIPTION ## updates the database where items are delimited by comma ## if there is a need for it # sub UpdateCommaDataBase { if ( ( $inHash{'TemplateMCdDb'} ) && ( $inHash{'dbDir'} ) && ( $inHash{'MasterCdDb'} ) && ( $inHash{'Operation'} eq 'saleslip' ) ) { &Logger( "UpdateCommaDataBase Begin" ); # update the master db file # with the customer's data if (! -e "$inHash{'MasterCdDb'}") { if ( ! open (MDB, ">$inHash{'MasterCdDb'}") ) { &Error( 'Sys_Open_MasterFile', $inHash{'MasterCdDb'} ); return 0; } } else { if ( ! open (MDB, ">>$inHash{'MasterCdDb'}") ) { &Error('Sys_Append_MasterFile', $inHash{'MasterCdDb'} ); return 0; } } $body = &ComposeDbBody( "$inHash{'TemplateMCdDb'}", "" ); print MDB "$body"; close ( MDB ); } } #F UpdateHtmlDataBase ## ## DESCRIPTION ## updates the html database if there is a need for it # sub UpdateHtmlDataBase { if ( ( $inHash{'IndexHtmlDb'} ) && ( $inHash{'dbDir'} ) && ( $inHash{'TemplateIndexDb'} ) && ( $inHash{'TemplateMHtmlDb'} ) && ( $inHash{'Operation'} eq 'saleslip' ) ) { &Logger( "UpdateHtmlDataBase Begin" ); #Update the master index file #Format the order according to index template $loggerMessage = "Update the master html database index file" . "according to template $inHash{'TemplateIndexDb'}"; $body = &ComposeDbBody( $inHash{'TemplateIndexDb'}, "" ); #Write the resulting body in the master index #First read in the contents of the master index if ( !open (HINDEXIN, "$inHash{'IndexHtmlDb'}") ) { &Error( 'Sys_Open_IndexFile', $inHash{'IndexHtmlDb'} ); return 0; } $index = join( '', ); close( HINDEXIN ); # Put the new record in the index body $index =~ s/()/$body\n$1/; # Then write out the new master index contents if ( !open( HINDEXOUT, ">$inHash{'IndexHtmlDb'}" ) ) { &Error( 'Sys_Open_IndexFile', $inHash{'IndexHtmlDb'} ); return 0; } print HINDEXOUT "$index\n"; close( HINDEXOUT ); ### Create the master order file $fileName = "$inHash{'dbDir'}/$inHash{'OrderHref'}"; $loggerMessage = "Format the html master order file" . "according to $inHash{'TemplateMHtmlDb'}"; $body = &ComposeDbBody( $inHash{'TemplateMHtmlDb'} ); if ( !open ( ORDER, ">$fileName") ) { &Error( 'Sys_Open_OrderFile', $fileName ); return 0; } print ORDER $body; close( ORDER ); } } #F SendEmailTo ## ## DESCRIPTION ## ## Check all of the addresses where must be sent e-mail and send it. ## ## Note that the presence of the 'Address' parameter implies that the ## caller would like us to Email data somewhere. ## Also consider if default address is present in $ADDRESS. ## See if 'ForwardAddress' is present. Then send a message to this address ## according to 'ForwardTemplate' file. ## ## NOTE: We only need to send E-mail if the 'Operation' CGI parameter was ## sent from the saleslip page and its value was "saleslip" ## # sub SendEmailTo { local( @sendMailTo ); &Logger( "SendEmailTo Begin" ); # generate the email body $body = &ComposeEmailBody( $inHash{'Template'} ); # Send the Email message to any specified addresses if ( $inHash{'Address'} ) { push( @sendMailTo, $inHash{'Address'} ); } if ( $inHash{'R_Address'} ) { push( @sendMailTo, $inHash{'R_Address'} ); } if ( $inHash{'Address2'} ) { push( @sendMailTo, $inHash{'Address2'} ); } if ( $inHash{'R_Address2'} ) { push( @sendMailTo, $inHash{'R_Address2'} ); } if ( $ADDRESS ) { push( @sendMailTo, $ADDRESS ); } foreach $addressElement ( @sendMailTo ) { &EmailIt( $addressElement, $inHash{'Subject'}, $body, $inHash{'FromAddress'} ); } if ( $inHash{'ForwardAddress'} ) { $body = &ComposeEmailBody( $inHash{'ForwardTemplate'} ); &EmailIt( $inHash{'ForwardAddress'}, $inHash{'Subject'}, $body, $inHash{'FromAddress'} ); } } #F LoadLastPage ## ## DESCRIPTION ## # sub LoadLastPage { &Logger( "LoadLastPage Begin" ); if ( ! open( PAGE, $lastPageToLoadName ) ) { &Error( 'Sys_Open_File', $lastPageToLoadName ); return 0; } $page = join( '', ); $page = &FormatShoppingCartData( $page, *inHash, "\n" ); &Logger( "Returned from FormatShoppingCartData call with $lastPageToLoadName" ); print "Content-type: text/html\n\n${page}"; return ; } #F main . . . . . . . . . . . . . . . . . . . . . . . . . . . .main function ## ## DESCRIPTION ## The module body parses the arguments given through the WWW page ## ## NOTE: ## The program is handling the following "Operation" types: ## 7. saleslip ## : sent by the saleslip page ## 8. final_confirm ## : sent by the checkout page # sub main { local( %inHash ); local( @inArray ); local( %conf ); local( $existDuplicates ); local( $lastPageToLoadName, $fileName ); $conf{'GENERAL_INFORMATION.ProgramName'} = $ProgramName; # read in scripts parameters if ( ! &ReadCgiParameters( *inHash, *inArray ) ) { &Error( 'Parameters_NoParameters', $0 ); } # check for Config File name, then parse the configuration file if ( ! defined $inHash{'ConfigFile'} ) { if ( ! defined $ConfigFile ) { &Error( 'Sys_Missing_ConfigFile', "" ); } else { $inHash{'ConfigFile'} = $ConfigFile; } } &ReadConfigFile( $inHash{'ConfigFile'}, *conf ); @RequiredElements = &CreateRequiredElements( "Fields" ); @CardElements = &CreateRequiredElements( "Cards" ); &UpdateInHash(); &CreateTaxTable(); ########################################################################### # Verify that we've got all our required fields. # However, we don't need to verify req'd fields if the user just # chose to "cancel" their order at the checkout page. ############################################################################ unless ( defined( $inHash{'Operation'} ) && ( $inHash{'Operation'} eq 'cancel') ) { &VerifyRequiredFields( *inHash ); &VerifyEmailAddresses( *inHash ); } &GetOrder(); $lastPageToLoadName = &SelectPageToLoad(); if ( ( !defined( $lastPageToLoadName ) ) || ( $lastPageToLoadName eq "" ) ) { &RedirectBrowser(); } ########################################################################## # Finally, we take care of saving the order in the database ########################################################################## &UpdateCommaDataBase(); &UpdateHtmlDataBase(); # Check if there is a need to send e-mail and in case send it. if ( ( defined( $inHash{'Operation'} ) ) && ( $inHash{'Operation'} eq "saleslip" ) && ( ( defined( $inHash{'Address'} ) ) || ( defined( $inHash{'Address2'} ) ) || ( defined( $inHash{'R_Address'} ) ) || ( defined( $inHash{'R_Address2'} ) ) || ( defined( $ADDRESS ) ) || ( defined( $inHash{'ForwardAddress'} ) ) ) ) { &SendEmailTo(); } if ( ( defined ( $lastPageToLoadName ) ) && ( $lastPageToLoadName ne "" ) ) { &LoadLastPage(); } &Logger( "Script done" ); &Logger( "-----------------------" ); } # end of main #E Emacs . . . . . . . . . . . . . . . . . . . . . . . local emacs variables ## ## Local Variables: ## mode: perl ## outline-regexp: "^#[A-Za-z]\\|^##[A-Za-z]" ## fill-column: 77 ## paragraph-start: "^##$\\\|^#$" ## paragraph-separate: "^##$\\\|^#$" ## eval: (outline-minor-mode) ## eval: (hide-body) ## End: #