#!/usr/local/bin/perl
#
# Note:  You may have to adjust the first line to point to the location of
#        your Perl interpreter.
#
# Program name:  shop.pl
# Author: Todd Hassan
# Creation date:  11/13/95
# Last modified: 4/8/98

$cart_version =  '1.18';

#
# Description:  This program is a shopping cart program.  It allows you to build 
#               a database file of your product list.  You then write HTML files
#               with the desciptions of your product.  These HTML files are passed
#               through shop.pl which looks for a token that tells it to insert
#               the shopper's id.  This shopper id or SID keeps track of which 
#               shopper you are in a hidden value in HTML.  This program uses
#               standard http links instead of forms.  The variables are passed
#               in the URL to shop.pl.  Shop.pl keeps track of what the shopper
#               has bought.  It totals their purchases and mails the completed
#               shopping list to the administrator. 
#
# Version History
# ---------------
# 1.02  Fixed round function  3/27/97
# 1.03  Added credit card checking function  4/4/97
# 1.04  Tweaked script to work with NT 4.0 4/28/97
# 1.05  Added ability to tell program what state you in and recalculate 
#       also redid &lookup_item
# 1.06  Added PUT_BUY_INFO_HERE tag and buy variable controls number of
#       items purchased 5/24/97 
# 1.07  Added ability to work with English pounds
# 1.08  Added ability to added multiple items on one form 6/23/97
# 1.09  Added CyberCash Module + different type of tax on subtotal 7/2/97
# 1.10  Added Secure Transaction Module 8/15/97
# 1.11  Fixed some bugs in the credit card checking algorithm 9/17/97
# 1.12  Changed POST routine to handle radio buttons 9/25/97
# 1.13  Fixed up mail output to look cleaner 9/26/97
# 1.14  Fixed size/color bug introduced by version 1.13 9/26/97
#       also removed server-side imagemap support.
# 1.15  Added UPS shipping cost option, added PUT_ZIP_HERE and 
#       PUT_STATE_HERE tokens.  Updated remove_list_files routine. 
#       updated shipping spacing in email receipt.  Added CALC_TAX_ON_SHIPPING
#       variable. 10/17/97
# 1.16  Improved replace_token routine.  Added MY_URL tag to allow cgi
#       to be automatically inserted.  Redid split routine. 
#       Added ability to do discounts. 12/12/97
# 1.17  Added new type of shipping algorithm, by price. 
#       Added gift wrap option and gift message.
#       Added ability to specify which fields are required in the
#       email form.  Added bstreet2 and street2 to mail form 1/16/98
# 1.18  Changed credit card date checking routine to work
#       with dates 2000 and over. Added search function. 
#       Added payment_type and company variables to email form.
#       Added 4 more shipping types (total of 8)
#       Added header and footer files to email receipts. 2/19/98
#
# Copyright Hassan Consulting 1996,1997,1998 All Rights Reserved
#
# set the location of your configuration file here

# require 'd:\website\cgi-bin\shop.cfg';
require './shop.cfg';

##########################################################################
#                 Do not change anything after this point!!!             #
##########################################################################

$product_list = "$shopping_root/$product_file";   # product list database file path
$SID_path = "$shopping_root/lists/sid";  # where to keep the current SID
$shopping_list_root = $shopping_root . "/lists/list";  # where to keep our shopping lists
@fields=(email,phone,name,street,street2,city,state,zip,country,bstreet,bstreet2,bcity,bstate,bzip,bcountry,comments,cctype,ccard,ccexpiry,gift_message,gift_wrapped,ccname,company);
@DESCRIPTION=("Email Address","Telephone Number","Name","Street Address","Street Address 2","City","State","Zip Code","Country", "Billing Street Address","Billing Street Address 2","Billing City","Billing State","Billing Zip Code","Billing Country","Comments","Credit Card Type","Credit Card Number","Credit Card Expiration Date","Gift Message","Gift Wrapped","Name on Credit Card", "Company Name");

# token to put in the HTML documents to be replaced with the SID

$ADDED = "";

# tokens

$buy_token = "PUT_BUY_INFO_HERE";
$myurl_token = "MY_URL";
$sid_token = "PUT_SID_HERE"; 
$shopping_token = "PUT_SHOPPING_LIST_HERE";  
$search_token = "PUT_SEARCH_RESULTS_HERE";  
$zip_token = "PUT_ZIP_HERE";
$state_token = "PUT_STATE_HERE";

$sid_length = length($sid_token);

# token to put in the HTML documents to be replaced with the shopping list

$prog = "shop.pl";

if ($ENV{'REQUEST_METHOD'} eq 'POST') 
{
  &split_post_data;
}

&split;

$page_path = $shopping_root . "/$FORM{page}";


# if no SID(Shopper ID) make one

if (($FORM{SID} eq "")||($FORM{SID} eq $sid_token))
{
  &make_sid;
  &remove_list_files;
}
else
{
  $sid = $FORM{SID};
}
$shopping_list = $shopping_list_root . $sid;

# buy the item if the customer wants to buy

if ($FORM{item} ne "")
{
  &buy;
}

# empty the cart

if ($FORM{empty} == 1)
{
  &empty_cart;
}

# recalculate the shopping list if requested

if ($FORM{recalculate} == 1)
{
  &recalculate;
}

# mail the completed shopping list to the administrator

if ($FORM{mail} == 1)
{
  if ((!($USE_CYBERCASH))&&(!($USE_SECURE)))
  { 
    &mail_list;  
  }
  elsif ($USE_CYBERCASH)
  {
    require './cyber.pl';
    &cyber_mail_list;
  }
  else
  {
    require './secure.pl';
    &secure_mail_list;
  }
  &empty_cart;
}
&html_header;

# parse the HTML page and replace the tokens

&parse_html;
exit 0;

# this routine splits the url path up into associative array

sub split 
{
    $split_value = "$ENV{PATH_TRANSLATED}";  # URL used 
    if ($NT)
    {
      @m_data = split(/\\/, $split_value);
    }
    else
    {
      @m_data = split(/\//, $split_value);
    }
    $m_size = @m_data;
    $num=0;
    for ($i=0;$i<$m_size;$i++)
    {
      if (index($m_data[$i], '=') != -1)
      {
        @t_data = split(/\=/, $m_data[$i]);
        $FORM{$t_data[0]} = $t_data[1];
        $POST{$t_data[0]} = $t_data[1];
        $num++;
      }
    }
    if ($FORM{page} eq "")
    {
      $FORM{page} = 'index.html';
    }
    if (!($num))
    {  
      &html_header;
      print("<a href=\"http://www.irata.com/\">Hassan Consulting's</a> Shopping Cart Version $cart_version<p>\n");
      exit(1);
    }
}

# lookup item in database file

sub lookup_item
{
  local($myitem) = shift;
  open (PRODUCT_LIST, "$product_list") || &sys_error("$prog: Error opening product list: $product_list\n");
  $data[0] = "";
  while ((!(eof(PRODUCT_LIST)))  && ($data[0] ne $myitem))
  {
    $line = <PRODUCT_LIST>;
    chop($line);
    if ($line ne "")
    {          
	@data = split(/\|/, $line);
        $num3 = @data;
        if ($num3 < 4)
        {
          &product_error;
        }
    }    
  }
  if ($data[0] ne $myitem)
  {
    &html_header;
    print("Error looking up item # $myitem<p></table></table></form>\n");
    exit(1);
  }
  $product_id = $data[0];
  $product_num = $data[1];
  $product_name = $data[2];
  $product_price = $data[3];
  $product_weight = $data[4];
}

sub product_error
{
    &html_header;
    print("ERROR in product list file\n");
    exit(1);
}

# just the content type because the HTML is all done in the HTML page parsed

sub html_header 
{
    print "Content-type: text/html\n\n";
}

# make a new sid

sub make_sid
{
    # read in the SID

    open (SID, $SID_path) || &sys_error("$prog: Error opening SID file: $SID_path\n"); 
    $sid = <SID>;
    close (SID); 

    # reset the SID at 40,000

    if (($sid > 40000) || ($sid < 0))
    {
	$sid = 0;
    }

    # write out the new SID 

    open (SID, ">$SID_path") || &sys_error("$prog: Error opening SID file: $SID_path\n"); 
    $temp = $sid + 1;
    $sid = $temp - 1; 
    print SID ("$temp\n");
    close (SID);

    # the process ID is part of the SID in case two users run make_sid at the same time

    $sid = $sid . "$$";  
}

# parse the HTML page provided and replace the SID and shopping_list tokens

sub parse_html
{
  open(HTML, "$page_path") || &sys_error("$prog: Error opening HTML file: $page_path\n"); 
  while (!(eof(HTML)))
  {
    $line = <HTML>;
    $x = index($line, "$buy_token");
    if ($x != -1)
    { 
      $pline = substr($line, 0, $x);
      $aline = substr($line, $x + (length($buy_token)) + 1);
      if ($FORM{item} ne "")
      {
        $line =  "$pline $ADDED $aline";
      }
      else
      {
        $line = "$pline$aline";
      }
      print("$line");
    }
    elsif (($x = index($line, "$shopping_token")) != -1)
    {
      $pline = substr($line, 0, $x);
      $aline = substr($line, $x + (length($shopping_token)) + 1);
      print("$pline");
      &shopping_cart;
      print("$aline");
    }
    elsif (($x = index($line, "$search_token")) != -1)
    {
      $pline = substr($line, 0, $x);
      $aline = substr($line, $x + (length($search_token)) + 1);
      print("$pline");
      &search;
      print("$aline");
    }
    else 
    {
      &read_list;
      if ($in_state eq 'Y')
      {
	$FORM{state} = $STATE;
      }
      $line = &replace_token($line, $myurl_token, $MY_URL);
      $line = &replace_token($line, $state_token, $FORM{state}); 
      $line = &replace_token($line, $zip_token, $FORM{zip});
      $line = &replace_token($line, $sid_token, $sid);
      print("$line");
    }
  }
  close (HTML);
}

# replace tokens

sub replace_token
{
  local($line) = shift;
  local($token) = shift;
  local($value) = shift;
  $pos = index($line, $token);
  while ($pos != -1)
  {
    $a = substr($line, 0, $pos);
    $b = substr($line, $pos + length($token));
    $line = "$a$value$b";
    $pos = index($line, $token);
  }
  return($line);
}

# print search results

sub search
{
  open (PRODUCT_LIST, "$product_list") || &sys_error("$prog: Error opening product list: $product_list\n");
  $num = 0;
  $FORM{query_string} = "\U$FORM{query_string}\E";
  if ($FORM{query_string} eq '')
  {
    $FORM{query_string} = 'nothing';
  }
  @keywords = split(/[\s]+/, $FORM{query_string});
  $query_size = @keywords;
  while (!(eof(PRODUCT_LIST)))
  {
    $line = <PRODUCT_LIST>;
    chop($line);
    $ok=1;
    $OR=0;
    if ($line ne "")
    {
      @data = split(/\|/, $line);
      for ($j=0;$j<$query_size;$j++)
      {
        if (!(index("\U$data[2]\E", $keywords[$j]) != -1))
        {
	  $ok=0;
        }
        else
        {
	  $OR=1;
        }
      }
      if (($ok)||(($OR)&&($FORM{query_type} eq 'OR')))
      {
        $RESULTS[$num] = $line;
        $num++;
      }
    }    
  }
  if ($num == 0)
  {
    print("Your search found nothing.<p>\n");
  }
  else
  {
    $next_page = $cart_page;
    if ($next_page eq "")
    {
      $next_page = 'shop.html';
    }
    $temp_url = &replace_token($MY_URL, $sid_token, $sid);
    $size = @RESULTS;
    @RESULTS = sort search_sort (@RESULTS);
    print("<table cellspacing=2 cellpadding=2 border=1><tr><td><b>Product Description</b></td><td><b>Product Code</b></td><td><b>Price</b></td></tr>\n");
    for($i=0;$i<$size;$i++)
    {
      @data = split(/\|/, $RESULTS[$i]);
      print("<tr><td>$data[2]<br></td><td>$data[1]<br></td><td align=right><a href=\"$temp_url/page=$next_page/buy=1/item=$data[0]\">$currency_symbol $data[3]</a><br></td></tr>\n");  
    }
    print("</table>\n");
  }
}

# search sort routine

sub search_sort
{
  @adata = split(/\|/, $a);
  @bdata = split(/\|/, $b);
  $ret = $adata[2] cmp $bdata[2]; 
  $ret;
}

# print out the shopping cart contents

sub shopping_cart
{
    &read_list;
    $item_total = 0;
    $subtotal = 0; 

    if ($num_lines > 0)
    {
      # print shipping info

      print("<table><tr><td>");

      if ($shipping_label{1} ne "")
      {
        print("<table cellspacing=2 cellpadding=2><tr><td colspan=2 align=\"top\"><b>Shipment Method</b></td></tr>\n");
        for ($k=1; $k<9; $k++)
        {
          if ($shipping_label{$k} ne "")
          {
            print("<tr><td></td><td><Input Name=\"shipby\" \n"); 
            print("Type=\"radio\"");
            if ($shipby eq $k)
            {
  	      print(" CHECKED ");
            }
            print("value=\"$k\"> $shipping_label{$k}</td></tr>\n");
          }
        }
        print("</table><br>");
      }

      # print list of items

      $ibuffer = "<table width=\"70\%\" cellspacing=2 cellpadding=2 border=1>";

      for ($i=1; $i<=$num_lines; $i++)
      {
        if ($i == 1)
        {
	  $ibuffer .= "<tr><td align=center><b>Qty</b></td><td align=center><b>Description</b></td><td align=center><b>Price</b></td></tr>\n";
        }
	$item_no = $ITEMS{$i};
        $color = $COLORS{$i};
        $size = $SIZES{$i};
	&lookup_item($item_no);
	$ibuffer .= "<tr><td><INPUT NAME=\"$i\" SIZE=3 MAXLENGTH=3 VALUE=\"$NUM{$i}\"></td>";

        $buf = "";
        if ($color ne "")
        {
          $buf .= "<b>Color:</b> $color<br>\n";
        }
        if ($size ne "")
        {
          $buf .= "<b>Size:</b> $size<br>\n";
        }
	$ibuffer .= "<td>$product_name<br>$buf</td>\n";
	$ibuffer .= "<td align=right>$currency_symbol $product_price</td></tr>";
        $item_total += $NUM{$i};
        $subtotal += ($product_price * $NUM{$i});       
      }
      $subtotal = &round($subtotal);
      $temp = $subtotal;  
      
      $ibuffer .= sprintf("\n<tr><td colspan=2 align=right>Subtotal</td><td align=right>$currency_symbol %9s</td></tr>\n", $temp);

      if ($DISCOUNT != 0)
      {
	$discount = &round($subtotal * $DISCOUNT);
        $subtotal = &round($subtotal - $discount);
        @j_data = split(/\./, $DISCOUNT);
        $temp = "$j_data[1]% Discount";
        $ibuffer .= sprintf("<tr><td colspan=2 align=right>%s </td><td align=right>- $currency_symbol %9s</td></tr>\n", $temp, $discount);
        $ibuffer .= sprintf("\n<tr><td colspan=2 align=right>New Subtotal </td><td align=right>$currency_symbol %9s</td></tr>\n", $subtotal);
      }

      $shipping = 0;
      if ($item_total > 0)
      {
	if ((($USE_UPS)&&($FORM{zip} ne ""))||(!($USE_UPS)))
        {
          $shipping = &calc_shipping($subtotal);
          if ($shipping_label{1} ne "")
          {
            $ibuffer .= "<tr><td colspan=2 align=\"right\">Shipping </td><td align=right>$currency_symbol $shipping</td></tr>\n";
          }
        }
      }
      if ((($tax_calc eq "")||($POST{tax_calc} eq 'Y')||($in_state eq 'Y'))&&($TAX))
      {
        if ($CALC_TAX_ON_SHIPPING eq 'N')
        {
          $tax = ($subtotal) * $tax_rate;
        }
        else
        {
          $tax = ($subtotal + $shipping) * $tax_rate;
        }
        $tax = &round($tax);
        if ($tax_rate != 0)
        {
          $ibuffer .= sprintf("<tr><td colspan=2 align=right>Tax</td><td align=right>$currency_symbol %9s</td></tr>\n", $tax);
        }
      }
      else
      {
        $tax=0;
      }
      $total = &round($tax + $shipping + $subtotal);
      $ibuffer .= sprintf("<tr><td colspan=2 align=right>Total </td><td align=right>$currency_symbol %9s", $total);
      $ibuffer .= "</td></tr></table>";
      $ibuffer .= "Total number of items: $item_total<br>\n";
      if ($TAX)
      {
        if (($tax_calc eq "")||($tax_calc eq "N"))
        {
          $ibuffer .= "(Tax added for $STATE billing addresses only)<br>\n";
        }
        else
        {
          if (($POST{tax_calc} eq 'Y')||($in_state eq 'Y'))
          {
	    $checked = "checked";
          }
          else
          { 
            $checked = "";
          }
	  print("</td><td valign=top><input name=tax_calc $checked type=checkbox value=Y><font size=-1>Check here and hit recalculate if you live in $STATE</font><br>"); 
        }
      } 
      if ($USE_UPS)
      {
        print("<br><font size=-1>Please fill in your zip code and hit recalculate to see your shipping charges<br>Zip Code: <input name=zip size=10 type=text value=\"$FORM{zip}\"></font><br>");
      }
      print("</td></tr></table>\n");
      print("$ibuffer\n");
  }
  else
  {
    print("Your shopping cart is empty.<BR>\n");
  }     
}

# calculate shipping

sub calc_shipping
{
  if ($shipping_label{1} eq "")
  {
    return(0);
  } 

  local($subtotal)=shift;
  local($done, $line, $myzip, $i, $item_no, $color, $size);
  
  if ((!($USE_UPS))||($shipby != 1))
  {
    if ($SHIPPING_ALGORITHM == 0) # by number of items
    {
      $shipping = $shipping_base{$shipby} + $item_total * $shipping_rate{$shipby};
    }
    elsif ($SHIPPING_ALGORITHM == 1) # by price
    {
      if ($shipby == 1)
      {
        $x=1;
        while(($subtotal > $shipping_base{$x})&&($x<200))
        {
          $x++;
        }
        $shipping = $shipping_rate{$x};
      } 
      if ($shipby == 2)
      {
        $x=1;
        while(($subtotal > $shipping_base2{$x})&&($x<200))
        {
         $x++;
        }
        $shipping = $shipping_rate2{$x};
      } 
      if ($shipby == 3)
      {
        $x=1;
        while(($subtotal > $shipping_base3{$x})&&($x<200))
        {
          $x++;
        }
        $shipping = $shipping_rate3{$x};
      } 
      if ($shipby == 4)
      {
        $x=1;
        while(($subtotal > $shipping_base4{$x})&&($x<200))
        {
          $x++;
        }
        $shipping = $shipping_rate4{$x};
      }
      if ($shipby == 5)
      {
        $x=1;
        while(($subtotal > $shipping_base5{$x})&&($x<200))
        {
          $x++;
        }
        $shipping = $shipping_rate5{$x};
      }
      if ($shipby == 6)
      {
        $x=1;
        while(($subtotal > $shipping_base6{$x})&&($x<200))
        {
          $x++;
        }
        $shipping = $shipping_rate6{$x};
      }
      if ($shipby == 7)
      {
        $x=1;
        while(($subtotal > $shipping_base7{$x})&&($x<200))
        {
          $x++;
        }
        $shipping = $shipping_rate7{$x};
      }
      if ($shipby == 8)
      {
        $x=1;
        while(($subtotal > $shipping_base8{$x})&&($x<200))
        {
          $x++;
        }
        $shipping = $shipping_rate8{$x};
      }
      if ($shipby == 4)
      {
        $x=1;
        while(($subtotal > $shipping_base4{$x})&&($x<200))
        {
          $x++;
        }
        $shipping = $shipping_rate4{$x};
      }
    }
  } 
  else
  {
    # weight per box is equal 

    local($weight) = 0;
    for ($i=1; $i<=$num_lines; $i++)
    {
      $item_no = $ITEMS{$i};
      $color = $COLORS{$i};
      $size = $SIZES{$i};
      &lookup_item($item_no);
      $weight += $product_weight * $NUM{$i};
    }
    $k = index($weight, '.');
    if ($k != -1)
    {
      $weight = substr($weight, 0, $k);
      $weight++;
    }

    if ($weight <= $weight_per_box)
    {
      $num_boxes = 1;
    }
    else
    {
      $num_boxes = ($weight / $weight_per_box);
      $k = index($num_boxes, '.');
      if ($k != -1)
      {
        $num_boxes = substr($num_boxes, 0, $k);
        $num_boxes++;
      }
      $weight = $weight / $num_boxes;
      $k = index($weight, '.');
      if ($k != -1)
      {
        $weight = substr($weight, 0, $k);
        $weight++;
      }      
    }

    # find zone

    if (!(open(ZONE, $zone_file)))
    {
      &file_error("$zone_file");
    }
    $FORM{zip} =~ s/\N//g;
    if (length($FORM{zip}) < 5)
    {
      print("</form></table></table></table>Error: Incorrect Zip Code<br>Use your <i>Back</i> button, and fill in the correct zip code, and hit recalculate.<br>\n");
      exit;
    }
    $myzip = substr($FORM{zip}, 0, 3);
    $done = 0;
    while((!(eof(ZONE)))&&(!($done)))
    {
      $line = <ZONE>;
      if ((substr($line,0,1)) eq '0')
      {
        $done = 1; 
      }  
    }
    local($zone) = 0;
    while((!(eof(ZONE)))&&(!($zone)))
    {
      @my_data = split(/\,/, $line);
      $my_pos = index($my_data[0], '-');
      if ($my_pos != -1)
      {
	@zip_array = split(/\-/, $my_data[0]);
        $from = $zip_array[0];
        $to = $zip_array[1];
      }
      else
      {
        $from = $my_data[0];
        $to = $my_data[0];
      }
      if (($myzip >= $from)&&($myzip <= $to))
      {
	$zone = $my_data[1];
      }
      $line = <ZONE>;
    }
    close(ZONE);

    # find rate
    
    if (!(open(RATE, $rate_file)))
    {
      &file_error("$rate_file");
    }
    $done = 0;

    while((!(eof(RATE)))&&(!($done)))
    {
      $line = <RATE>;
      if ((substr($line,0,1)) eq '1')
      {
        $done = 1; 
      }  
    }
    $shipping = 0;
    while((!(eof(RATE)))&&(!($shipping)))
    {
      $line =~ s/[\$ ]//g;
      @my_data = split(/\,/, $line);  
      $my_weight = $my_data[0];
      if ($my_weight == $weight)
      {
	$shipping = $my_data[$zone - 1];
      }
      $line = <RATE>;
    }
    close(RATE);
    $shipping = $shipping * $num_boxes;
    $shipping += ($item_total * $handling);
  }
  $shipping = &round($shipping);
  return($shipping);
}

# file opening error

sub file_error
{
  local($temp);
  $temp = shift;
  print("</table></form></table></table><a href=\"http://www.irata.com/\">Hassan Consulting's</a> Shopping Cart Version $cart_version<p>Error opening $temp<p>Please inform the administrator at <b>$admin</b> of this error.<p>");
  exit;
}

# round the total 

sub round
{  
  local($num) = @_;
  $num = sprintf("%9.2f", $num);
  $num =~ s/^[ ]+//g;
  return($num);
}

# buy item(s) and add to the shopping list

sub buy
{	
  &read_list;

  if (index($FORM{item}, '|') == -1)
  {
    $my_item = $FORM{item};
    $color = $FORM{color};
    $size = $FORM{size};
    if ($FORM{buy} eq "")
    {
      $color = $FORM{"color$my_item"};
      $size = $FORM{"size$my_item"};
      $FORM{buy} = $FORM{"buy$my_item"};    
    }
    $split_size=1;
    $split_me = 0;
  }
  else
  {
    $split_me = 1;
    @item_array = split(/\|/, $FORM{item});
    $split_size = @item_array;
  }
  for ($k=0;$k<$split_size;$k++)
  {
    if ($split_me)
    {
      $my_item = $item_array[$k];
      $color = $FORM{"color$my_item"};
      $size = $FORM{"size$my_item"};    
      $FORM{buy} = $FORM{"buy$my_item"};  
    }
    if ($FORM{buy} > 0)
    {
      $foundit = 0;
      for ($i=1; $i<=$num_lines; $i++)
      {
        if (($ITEMS{$i} == $my_item) && ($COLORS{$i} eq $color) && ($SIZES{$i} eq $size))
        {
          $foundit = 1;
        }
      }
   
      if ($foundit)
      {
        $number_items = 1;
        for ($i=1; $i<=$num_lines; $i++)
        {
          if (($ITEMS{$i} == $my_item) && ($COLORS{$i} eq $color) && ($SIZES{$i} eq $size))
          {
            $number_items = $i;          
            $NUM{$i} += $FORM{buy};
          }
        }
        $COLORS{$number_items} = $color;
        $SIZES{$number_items} = $size;
      }
      else
      {
        $num_lines++;
        $NUM{$num_lines} = $FORM{buy};
        $ITEMS{$num_lines} = $my_item;
        $COLORS{$num_lines} = $color;
        $SIZES{$num_lines} = $size;
      }
      &lookup_item($my_item);
      $ADDED .= "$product_name, "; 
    }
  }
  &write_list;
  chop($ADDED);
  chop($ADDED);
  $ADDED .= " added to your cart";
}

# read in the shopping list

sub read_list
{
    open (LIST, "$shopping_list"); 
    $num_lines = 0;
    $in_state = <LIST>;
    chop($in_state);
    $shipby = <LIST>;
    chop($shipby);
    $zip = <LIST>;
    chop($zip);
    if ($shipby eq "")
    {
      $shipby=1;
    }
    if ($FORM{zip} ne "")
    {
      $zip=$FORM{zip};
    }
    else
    {
      $FORM{zip} = $zip;
    }
    
    while (!(eof(LIST)))
    {			
	$item_no = <LIST>;
	chop($item_no);
	if ($item_no ne "")
	{
	    $num_lines++;
	    $ITEMS{$num_lines} = $item_no;
	    $NUM{$num_lines} = <LIST>;
            chop($NUM{$num_lines});
	    $COLORS{$num_lines} = <LIST>;
            chop($COLORS{$num_lines});
	    $SIZES{$num_lines} = <LIST>;
            chop($SIZES{$num_lines});
        }
    }
    close (LIST);
    $total_num_items = $num_lines;
}

sub empty_cart
{
    open (LIST, ">$shopping_list");
    print LIST ("$in_state\n");
    print LIST ("$shipby\n");
    print LIST ("$zip\n");
    close(LIST); 
}

# write out the shopping list

sub write_list
{
    open (LIST, ">$shopping_list") || &sys_error("$prog: Error opening shopping list for write: $shopping_list\n");
    print LIST ("$in_state\n");
    print LIST ("$shipby\n");
    print LIST ("$zip\n");
    for ($j=1; $j<=$num_lines; $j++)
    {
	if ($NUM{$j} > 0)
	{    
	    print LIST ("$ITEMS{$j}\n");
	    print LIST ("$NUM{$j}\n"); 
	    print LIST ("$COLORS{$j}\n"); 
	    print LIST ("$SIZES{$j}\n"); 
        }
    }
    close (LIST);
    @file_list = ("$shopping_list");
    chmod (0644, @file_list);
}

# recalculate the shopping list

sub recalculate
{
    &read_list;
    foreach $sub (keys (%POST))
    {	
      if ($sub ne "shipby")
      {
        $NUM{$sub} = $POST{$sub};
      }
    }
    $shipby = $POST{shipby};
    $in_state = $POST{tax_calc};
    &write_list;
}

# email customer information

sub mail_list
{
  &read_list;

  $info_buffer = '';
  $header_buffer = '';
  $cc_buffer = '';
  $order_buffer = '';

  for ($i=1; $i<=$num_lines; $i++)
  {
    $item_no = $ITEMS{$i};
    &lookup_item($item_no); 
  }

  $item_total = 0;
  $subtotal = 0;
  $output = "";

  # for NT only

  $mail_file = "$temp_location/shop$$.txt";

  &check_email_form;

  $item_total = 0;
  $subtotal = 0;
  $mail1 = "";
  if ($NT)
  {
    $mail = "$mail_location $mail_file -t $admin -f $admin -s \"$admin_subject\"";
    if ($admin1 ne "")
    {    
      $mail1 = "$mail_location $mail_file -t $admin1 -f $admin -s \"$admin_subject\"";
    }
    if (!(open(MAIL, ">$mail_file")))
    {
      &html_header;
      print("Error opening mail file: $mail_file<P>\n");
      exit(1);
    }
  }
  else
  {
    $mail = "$mail_location -oi -t";
    open(MAIL, "| $mail") || &sys_error("$prog: Can't open pipe to sendmail: $!");
    if ($admin1 ne "")
    { 
      $header_buffer .= "To: $admin, $admin1\r\n";
    }
    else
    { 
      $header_buffer .= "To: $admin\r\n";
    }
    $header_buffer .= "X-Mailer: Hassan Consulting Shopping Cart \r\n";
    $header_buffer .= "Mime-Version: 1.0\r\n";
    $header_buffer .= "Content-Type: text/plain; charset=$char_set\r\n";
    $header_buffer .= "From: $admin\r\n";
    $header_buffer .= "Reply-to: $POST{email}\r\n";
    $header_buffer .= "Subject: $admin_subject\r\n\r\n";
  }
  $head= '';
  if ($header_file ne "")
  {
    $file = "$shopping_root/$header_file";
    open(HEAD, $file);
    while (!(eof(HEAD)))
    { 
      $head .= <HEAD>;
    }
    close(HEAD);
  }
  $info_buffer .= "Name: $POST{name}\r\n";
  $info_buffer .= "Email: $POST{email}\r\n";
  $info_buffer .= "Shipping Address: $POST{street}\r\n";
  if ($POST{street2} ne "")
  {
    $info_buffer .= "$POST{street2}\r\n";
  }
  $info_buffer .= "$POST{city} $POST{state} $POST{zip} $POST{country}\r\n";
  if ($POST{bstreet} ne "")
  {
    $info_buffer .= "Billing Address: $POST{bstreet}\r\n";
    if ($POST{bstreet2} ne "")
    {
      $info_buffer .= "$POST{bstreet2}\r\n";
    }
    $info_buffer .= "         $POST{bcity} $POST{bstate} $POST{bzip} $POST{bcountry}\r\n";
  }
  $info_buffer .= "Phone: $POST{phone}\r\n";
  if ($POST{company} ne "")
  {
    $info_buffer .= "Company Name: $POST{company}\r\n";
  }
  if ($POST{comments} ne "")
  {
    $info_buffer .= "Comments: $POST{comments}\r\n";
  }
  if ($POST{payment_type} ne "")
  {
    $info_buffer .= "Payment Type: $POST{payment_type}\r\n";
  }
  if (($POST{payment_type} ne 'check')&&($POST{payment_type} ne 'money_order')&&($POST{payment_type} ne 'wire_transfer'))
  {
    $cc_buffer .= "Credit Card Type: $POST{cctype}\r\n";
    $cc_buffer .= "Expiration Date: $POST{ccexpiry}\r\n";
    $cc_buffer .= "Credit Card #: $POST{ccard}\r\n";
    $cc_buffer .= "Exact Name: $POST{ccname}\r\n";
  }
  $order_buffer .= "\r\nOrder:\r\n";
  $order_buffer .= "-------------------------------------------------------------------\r\n";

  if ($num_lines > 0)
  {
    for ($i=1; $i<=$num_lines; $i++)
    {
      $item_no = $ITEMS{$i};
      $color = $COLORS{$i};
      $size = $SIZES{$i};
      &lookup_item($item_no);   
      $order_buffer .= sprintf("%-4s %-7s %-45s %8s\r\n", $NUM{$i}, $product_num, $product_name, $product_price); 
      $doit=0;
      if ($color ne "")
      {
        $order_buffer .= "Color: $color  ";
        $doit=1;
      }
      if ($size ne "")
      {
        $order_buffer .= "Size: $size";
        $doit=1;
      }
      if ($doit)
      {
        $order_buffer .= "\r\n";
      }
      $subtotal += $product_price * $NUM{$i};
      $item_total += $NUM{$i};
    }
    
    $subtotal = &round($subtotal);
    $temp = $subtotal;
    $temp1 = $item_total;
    $order_buffer .= sprintf("\r\nTotal # items: %-4s                             Subtotal  $email_currency_symbol%8s\r\n", $temp1, $temp);

    if ($DISCOUNT != 0)
    {
      $discount = &round($subtotal * $DISCOUNT);
      $subtotal = &round($subtotal - $discount);
      @j_data = split(/\./, $DISCOUNT);
      $temp = "$j_data[1]% Discount";
      $minus = "-$discount";
      $order_buffer .= sprintf("                                            %s  $email_currency_symbol%8s\r\n", $temp, $minus);
      $order_buffer .= sprintf("                                            New Subtotal  $email_currency_symbol%8s\r\n", $subtotal);
    }

    $shipping = &calc_shipping($subtotal);
    $my_temp = "( $shipping_label{$shipby} )";
    if ($shipping_label{1} ne "")
    { 
      $order_buffer .= sprintf("                          %20s  Shipping  $email_currency_symbol%8s\r\n",$my_temp,$shipping);
    }

    if ($POST{bstate} ne "")
    {
	$state = $POST{bstate};
    }
    else
    { 
 	$state = $POST{state};
    }  
    if (("\U$state\E" eq $STATE)&&($TAX))
    {
      if ($CALC_TAX_ON_SHIPPING eq 'N')
      {
        $tax = ($subtotal) * $tax_rate;
      }
      else
      {
        $tax = ($subtotal + $shipping) * $tax_rate;
      }
      $tax = &round($tax);
      $order_buffer .= sprintf("                                                     Tax  $email_currency_symbol%8s\r\n", $tax);
      $total = &round($tax + $subtotal+ $shipping);
    }
    else
    {
      $total = &round($subtotal + $shipping);
    }
    $total = &round($total);
    $order_buffer .= sprintf("                                                   Total  $email_currency_symbol%8s\r\n", $total);
  }     
  &check_gift;
  $foot= '';
  if ($footer_file ne "")
  {
    $file = "$shopping_root/$footer_file";
    open(FOOT, $file);
    while (!(eof(FOOT)))
    { 
      $foot .= <FOOT>;
    }
    close(FOOT);
  }
  print MAIL "$header_buffer";
  print MAIL "$info_buffer";
  print MAIL "$cc_buffer";
  print MAIL "$order_buffer";
  close (MAIL) || &sys_error("$prog: Error closing pipe to sendmail: $!");;
  if ($NT)
  {
    `$mail`;
    if ($mail1 ne "")
    {
      `$mail1`;
    }
  }

# send receipt to customer  
 
  if ($FORM{email} ne "") 
  {
  if ($NT)
  {
    $mail = "$mail_location $mail_file -t $POST{email} -f $admin -s \"$customer_subject\"";

    if (!(open(MAIL, ">$mail_file")))
    {
      &html_header();
      print("Error opening mail file: $mail_file<P>\n");
      exit(1);
    }
  }
  else
  {
    open(MAIL, "| $mail") || &sys_error("$prog: Can't open pipe to sendmail: $!");
    $header_buffer = '';
    $header_buffer .= "To: $POST{email}\r\n";
    $header_buffer .= "X-Mailer: Hassan Consulting Shopping Cart \r\n";
    $header_buffer .= "Mime-Version: 1.0\r\n";
    $header_buffer .= "Content-Type: text/plain; charset=$char_set\r\n";
    $header_buffer .= "From: $admin\r\n";
    $header_buffer .= "Subject: $customer_subject\r\n\r\n";
  }
  print MAIL "$header_buffer";
  print MAIL "$head";
  print MAIL "$info_buffer";
  print MAIL "$order_buffer";
  print MAIL "$foot";
  close (MAIL) || &sys_error("$prog: Error closing pipe to sendmail: $!");;
  if ($NT)
  {
    `$mail`;
    @delete_list = ("$mail_file");
    unlink(@delete_list);
  }
  }
}

# check for gift wrap and message

sub check_gift
{
  if ($POST{gift_wrapped} eq 'Y')
  {
    $order_buffer .= "\r\nThis package will be gift wrapped.\r\n";
  }

  if ($POST{gift_message} ne '')
  {
    $order_buffer .= "\r\nGift Message\n------------\n$POST{gift_message}\r\n";
  }
}

# check email for completeness

sub check_email_form
{
  $output = "";

  #  Do some checks on the input

  if ((($POST{email} !~ /^[a-zA-Z0-9_\-+ \t\/@%!.]+$/ ||
    $POST{email} !~ /[@%!]/))&&($REQUIRED[0] eq 'Y')) 
  {
    $output .= "Error: Illegal Email Address.<br>\n";
  }
  $FORM{zip} =~ s/\N//g;
  if (($USE_UPS)&&(length($FORM{zip}) < 5))
  {
    $output .= "Error: Incorrect Zip Code.<br>\n"
  }
  $size = @fields;
  for($i=1;$i<$size;$i++)
  {
    if (($REQUIRED[$i] eq 'Y')&&($FORM{$fields[$i]} eq ""))
    {
      $output .= "The field <b>$DESCRIPTION[$i]</b> must be filled out.<br>\n";
    }
  }

  if ($num_lines < 1)
  {
    $output .= "Error: Nothing in your shopping basket.<br>\n"
  }
  if ($CHECK_CC_NUM)
  {
    &check_card_number;
  }
  if ($output ne "")
  {
    &html_header;
    print("<a href=\"http://www.irata.com/\">Hassan Consulting's</a> Shopping Cart Version $cart_version<p>$output<P>Please use your <i>Back</i> button to correct the error(s) and resubmit the data.<p>");
    exit(1);
  }
}


# split the POST data into the POST array

sub split_post_data
{
  read(STDIN, $buffer, $ENV{CONTENT_LENGTH});

  #  Split the name/value pairs on '&'

  @pairs = split(/&/, $buffer);

  #  Determine the name and value for each form variable

  foreach $pair (@pairs) 
  {
    ($name, $value) = split(/=/, $pair);  # split on equals
    $value =~ tr/+/ /;  # turn pluses into spaces

    # convert hex values

    $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
    if ((($name eq 'item')&&($FORM{item} ne ""))||($name =~ /item[\d]+/))
    {      
      $POST{item} .= "|$value";
      $FORM{item} .= "|$value";
    }
    else
    {
      $POST{$name} = "$value";
      $FORM{$name} = "$value";
    }
  }
}

# print error message and exit

sub sys_error
{
  local($msg) = shift;
  &html_header;
  print("<a href=\"http://www.irata.com/\">Hassan Consulting's</a> Shopping Cart Version $cart_version<p>\n");
  print ("$msg\n");
  exit (1); 
}

# erase old list files older than 2 days

sub remove_list_files
{
  $cur_time = time();
  if (!(opendir(LISTDIR, "$shopping_root/lists")))
  {
    &html_header;
    print("Error: unable to open lists directory: $shopping_root/lists");
    exit(1);
  }

  while ($filename = readdir(LISTDIR))
  {
    if (substr($filename, 0, 4) eq "list")
    {
      @old = stat("$shopping_root/lists/$filename");
      @old_stat = localtime($old[9]);
      @cur_time_stat = localtime($cur_time);
      $del_year = $cur_time_stat[5] - $old_stat[5];
      if (($cur_time_stat[7] + 365 * $del_year)> ($old_stat[7] + 1))
      {
        @delete_list = ("$shopping_root/lists/$filename");
        unlink(@delete_list);
      }
    }
  }
  closedir(LISTDIR);
}

# check cc info

sub check_card_number
{
  $cc=$POST{ccard};
 
  if (length($cc)<2)
  {
    $output .= "Credit Card field must be filled out<P>";
  }
  else
  {
  $error = 0;
  $cc =~ s/\D//g;
  $length = length($cc);
  if (($length < 13) || ($length > 16))
  {
    $error = 1;
  }
  $first = substr($cc, 0, 1);
  $card_type = "none";
  if ($first == 5)
  {
    $card_type = "MasterCard";
    if ($length != 16)
    {
      $error = 1;
    }
  }
  if ($first == 4)
  {
    $card_type = "Visa";
    if (($length != 16) && ($length != 13))
    {
      $error = 1;
    }
  }
  if ($first == 3)
  {
    $card_type = "American Express";
    if ($length != 15)
    {
      $error = 1;
    }
  }
  if ($first == 6)
  {
    $card_type = "Discover";
    if ($length != 16)
    {
      $error = 1;
    }
  }
  if ($card_type eq "none")
  {
    $error = 1;
  }
  if (!($error))
  {
    $z = 2;
    $sum = 0;

    for ($i = $length - 2; $i>=0; $i--) 
    {
      $cdigit = substr($cc, $i, 1);  
      $prod = $z * $cdigit;
      $ones= chop($prod); 
      $sum += $ones + $prod;			
      $z = $z % 2 + 1;   
    }

    if (!(substr($cc, $length - 1, 1) == (10 - ($sum % 10)) % 10))
    {
      $error = 1;
    }
  }
  if ($error)
  {
    $output .= "The <b>Credit Card Number</b> you entered: <b>$POST{ccard}</b> is invalid.<br>\n";
  }
  }
  @current_time = localtime(time());
  $month = $current_time[4]+1;
  $year = $current_time[5];
  if ($year < 171)
  {
    if ($year < 50)
    {
      $year += 2000;
    }
    else
    {
      $year += 1900;
    }     
  } 
  @date_split = split(/\//, $POST{ccexpiry});
  if ($date_split[1] < 171)
  {
    if ($date_split[1] < 50)
    {
      $date_split[1] += 2000;
    }
    else
    {
      $date_split[1] += 1900;
    }     
  } 
  if (!((length($date_split[0]) > 0)&&(length($date_split[0]) < 3)))
  {
    $output .= "The date <b>$POST{ccexpiry}</b>, you entered for your credit card expiration date is invalid.  It must be in this format: MM/YY.<br>\n";
  }
  elsif (length($date_split[1]) != 4)
  {
    $output .= "The date <b>$POST{ccexpiry}</b>, you entered for your credit card expiration date is invalid.  It must be in this format: MM/YY.<br>\n";
  }
  elsif (($year > $date_split[1])||(($year == $date_split[1])&&($month > $date_split[0])))
  {
    $output .= "The date <b>$POST{ccexpiry}</b>, you entered for your credit card expiration date is expired.<br>\n";
  }
}
