#!/usr/bin/perl -wT use CGI qw(:standard); use CGI::Carp qw(warningsToBrowser fatalsToBrowser); use DBI; use strict; my $item = $ENV{QUERY_STRING}; # connect to the database my $dbh = DBI->connect( "dbi:mysql:products", "webserver", "", { RaiseError => 1, AutoCommit => 1 }) or &dienice("Can't connect to database: $DBI::errstr"); # 1. First be sure the item they're ordering is actually valid. No # point in setting cookies for bogus items. if ($item =~ /\D/) { # make sure the item number is alphanumeric. &dienice("Item `$item' is not a valid item number."); } my $sth = $dbh->prepare("select * from items where stocknum=?") or &dbdie; $sth->execute($item) or &dbdie; if (my $rec = $sth->fetchrow_hashref) { if ($rec->{status} eq "OUT") { # out of stock. They can't order it. &dienice("We're sorry, but $rec->{name} (item #$item) is out of stock."); } } else { &dienice("There is no item numbered `$item' in the database."); } # 2. See if a cookie has already been set (and is valid). my $cookie_id; if (cookie('cart')) { # found a cookie! see if it's valid... $sth = $dbh->prepare("select * from cart_cookies where cookie_id=?") or &dbdie; $sth->execute(cookie('cart')) or &dbdie; if ($sth->fetchrow_hashref) { $cookie_id = cookie('cart'); } } # 2a. If no cookie was found, set one. if ($cookie_id) { # A valid cookie was found. Print a regular header. print header(); } else { # no valid cookie found, so set one. $cookie_id = &random_id(); my $cookie = cookie(-name=>'cart', -value=>$cookie_id, -expires=>'+7d'); $sth = $dbh->prepare("insert into cart_cookies values(?,current_timestamp())") or &dbdie; $sth->execute($cookie_id) or &dbdie; print header(-cookie=>$cookie); } # 3. Add the ordered item to the shopping cart table. # If they already ordered one of these items, increment the QTY # Otherwise, insert a new record with QTY=1. $sth = $dbh->prepare("select * from shopcart where cookie=? and item_number=?") or &dbdie; $sth->execute($cookie_id, $item) or &dbdie; if ($sth->fetchrow_hashref) { $sth = $dbh->prepare("update shopcart set qty=qty+1 where cookie=? and item_number=?") or &dbdie; $sth->execute($cookie_id, $item) or &dbdie; } else { $sth = $dbh->prepare("insert into shopcart values(?,?,?)") or &dbdie; $sth->execute($cookie_id, $item, 1) or &dbdie; } # 4. Display the shopping cart print start_html("Add Item"); &display_shopcart($cookie_id); print end_html; sub random_id { # This routine generates a 32-character random string # out of letters and numbers. my $rid = ""; my $alphas = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; my @alphary = split(//, $alphas); foreach my $i (1..32) { my $letter = $alphary[int(rand(@alphary))]; $rid .= $letter; } return $rid; } sub dienice { my($msg) = @_; print header; print start_html("Error"); print "<h2>Error</h2>\n"; print $msg; exit; } sub display_shopcart { my($cookie_id) = @_; my $sth = $dbh->prepare("select * from shopcart, items where shopcart.cookie=? and items.stocknum=shopcart.item_number") or &dbdie; $sth->execute($cookie_id) or &dbdie; my $subtotal = 0; print qq( <center> <h3>Your Shopping Cart</h3> <form action="edcart.cgi" method="POST"> <table border=0 width=70%> <tr> <th bgcolor="#cccccc">Item Number</th> <th bgcolor="#cccccc">Name</th> <th bgcolor="#cccccc">Price</th> <th bgcolor="#cccccc">Qty.</th> </tr> ); while (my $rec = $sth->fetchrow_hashref) { $subtotal = $subtotal + ($rec->{price} * $rec->{qty}); print qq( <tr> <td align="CENTER">$rec->{item_number}</td> <td align="CENTER">$rec->{name}</td> <td align="CENTER">\$$rec->{price}</td> <td align="CENTER"><input type="text" name="item_$rec->{item_number}" size=3 value="$rec->{qty}"></td> </tr> ); } $subtotal = sprintf("%4.2f", $subtotal); print qq( <tr> <td></td> <td></td> <td><b>Subtotal:</b> \$$subtotal</td> <td></td> </tr> </table> <input name="cartact" type="submit" value="Update Qty"> <input name="cartact" type="submit" value="Check Out"> </form> </center> ); } sub dbdie { my($package, $filename, $line) = caller; my($errmsg) = "Database error: $DBI::errstr<br> called from $package $filename line $line"; &dienice($errmsg); }