All pastes #41491 Raw Edit

Stuff

public text v1 · immutable
#41491 ·published 2006-02-13 22:46 UTC
rendered paste body
#!/usr/bin/perl

use warnings;
use strict;

# the first argument of this function is a filename
# the second argument is a reference to a hash of variables
# all variables in that hash will be written out to a file
# the format of the file is as follows
# SCALARS: s:name:value
# ARRAYS : a:name:value1:value2:value3
# HASHES : h:name:key1:value1:key2:value2
# newlines are the seperators! there is no terminating character
sub write_hash {
    my $filename = shift @_;
    my $vars = shift @_;
   
    open(FILE, ">$filename");
    
    foreach my $key (keys %{$vars}) {
        # this one is just for convienence
        my $i = \( $vars->{$key} );

        # this is a switch statement
        # make a reference to $vars->{$key} and pass it to ref
        for (ref $i) {
            # if it is scalar, ref will return SCALAR...
            if (/SCALAR/) {
                print FILE "s:$key:" . $vars->{$key} . "\n";
            }
            # ...otherwise it returns an empty string
            # which means it is a hash or an array
            else {
                my $j = $vars->{$key};
                my $type = ref $j;
                # if it is an array, print out each element
                if ($type eq "ARRAY") {
                    print FILE "a:$key";
                    for my $element ( @{$j} ) {
                        print FILE ":$element";
                    }
                    print FILE "\n";
                }
                # likewise for a hash, print out the key/value pairs
                elsif ($type eq "HASH") {
                    print FILE "h:$key";
                    for my $k ( keys %{$j} ) {
                        print FILE ":$k:" . $j->{$k};
                    }
                    print FILE "\n";
                }
            }
        }
    }
   
    close(FILE);
        
    return;
}

# the first argument of this function is a filename
# function returns a hash
# see the above function for the format of the file
sub read_hash {
    my $filename = shift @_;
    my %vars;
    # these are used when extracting data from the fields
    my ($type, $name, $value, $key);

    print STDERR "$filename\n";
    open(FILE, "$filename");
    my @data = <FILE>;
    close(FILE);

    # iterate through the array 
    foreach my $line (@data) {
        # retrieve the type
        $type = substr($line, 0, 1);
        for ($type) {
            # if it's a scalar...
            if (/s/) {
                (undef,$name,$value) = split(/:/, $line, 3);
                chomp $value;
                $vars{$name} = $value;
            }
            # if it's an array...
            if (/a/) {
                # stores the elements of the array, temporarily
                my ($values, @elements);
                (undef,$name,$values) = split(/:/, $line, 3);
                chomp $values;
                @elements = split(/:/, $values);

                # now we've got the values split up
                # time to write things to the hash
                $vars{$name} = (\@elements);
            }
            # if it's a hash...
            if (/h/) {
                # $k and $v are for key and value
                my ($k, $v, $pairs, %hash);
                (undef,$name,$pairs) = split(/:/, $line, 3);
                chomp $pairs;

                # extract all the pairs and put them in the hash
                while (defined $pairs) {
                    ($k,$v,$pairs) = split(/:/, $pairs, 3);
                    $hash{$k} = $v;
                }

                # now shove a hash ref into our big hash!
                $vars{$name} = \%hash;
            }
        }
    }
    
    return %vars;
}

sub write_start {
    # get the error message, if there is one
    # undefined if there is no errmsg
    my $errmsg = shift(@_);

    print "Content-Type: text/html";
    print "\n\n";
    print '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
    print '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ';
    print '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' . "\n";
    print '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">' . "\n";
    print '<head>' . "\n";
    print '<link rel="StyleSheet" href="css/assign1.css" type="text/css" ';
    print 'media="screen" title="mystyle" />' . "\n";
    print '<title>Restaurant Bill Calculator</title>' . "\n";
    print '</head>' . "\n";
    print '<body>' . "\n";
    print '<form action="assign1.cgi" method="get" name="patrons">' . "\n";
    if (defined $errmsg) {
        print '<div class="error">' . $errmsg . '</div>' . "\n";
        print '<br />' . "\n";
    }
    print '<table>' . "\n";
    print '<tr>' . "\n";
    print '<td class="label">Number of Patrons: </td>';
    print '<td class="value">' . "\n";
    print '<input type="text" name="patrons" size="6" maxlength="10" />' . "\n";
    print '</td>' . "\n";
    print '</tr><tr>' . "\n";
    print '<td align="center" colspan="2">' . "\n";
    print '<input type="submit" name="go" value="submit" />' . "\n";
    print '</td>' . "\n";
    print '</tr>' . "\n";
    print '</table>' . "\n";
    print '<input type="hidden" name="file" value="patron" />' . "\n";
    print '</form>' . "\n";
    print '</body>' . "\n";
    print '</html>' . "\n";
    
    return;
}

sub write_appetizer {
    # get the session id...
    my $session_id = shift @_;

    # this will have an error message if one was passed, and will be
    # undefined otherwise
    my $errmsg = shift @_;
    
    # ...and write the page
    print "Content-Type: text/html";
    print "\n\n";
    print '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
    print '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ';
    print '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' . "\n";
    print '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">' . "\n";
    print '<head>' . "\n";
    print '<link rel="StyleSheet" href="css/assign1.css" type="text/css" ';
    print 'media="screen" title="mystyle" />' . "\n";
    print '<title>Restaurant Bill Calculator - Appetizers</title>' . "\n";
    print '</head>' . "\n";
    print '<body>' . "\n";
    print '<form action="assign1.cgi" method="get" name="appetizer">' . "\n";
    if (defined $errmsg) {
        print '<div class="error">' . $errmsg . '</div>' . "\n";
    }
    print '<table style="form">' . "\n";
    print '<tr>' . "\n";
    print '<td class="label">Appetizers: </td>' . "\n";
    print '<td class="value">' . "\n";
    print '<select name="appetizer">' . "\n";
    print '<option value="garlic bread">Garlic Bread ($3.95)</option>' . "\n";
    print '<option value="brushetta">Brushetta ($4.95)</option>' . "\n";
    print '<option value="hummus">Humous & Tabouleh ($5.95)</option>' . "\n";
    print '</select>' . "\n";
    print '</tr><tr>' . "\n";
    print '<td class="label">Quantity: </td>' . "\n";
    print '<td class="value">';
    print '<input type="text" name="qty" size="6" maxlength="2" />' . "\n";
    print '</td>' . "\n";
    print '</tr><tr>' . "\n";
    print '<td class="label">Add more? </td>' . "\n";
    print '<td class="value"><input type="checkbox" name="more" /></td>' ."\n";
    print '</tr><tr>' . "\n";
    print '<td align="center" colspan="2">';
    print '<input type="submit" name="go" value="Submit" />';
    print '</td>' . "\n";
    print '</table>' . "\n";
    print '<input type="hidden" name="file" value="appetizer">' . "\n";
    print '<input type="hidden" name="session_id" value="' . $session_id
                                                           . '">' . "\n";
    print '</form>' . "\n";
    print '</body>' . "\n";
    print '</html>' . "\n";

    return;
}

sub write_entree {
    # retrieve the session id...
    my $session_id = shift @_;
    # ...and write the page
    print "Content-Type: text/html";
    print "\n\n";
    print '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
    print '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ';
    print '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' . "\n";
    print '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">' . "\n";
    print '<head>' . "\n";
    print '<link rel="StyleSheet" href="css/assign1.css" type="text/css" ';
    print 'media="screen" title="mystyle" />' . "\n";
    print '<title>Restaurant Bill Calculator - Entrees</title>' . "\n";
    print '</head>' . "\n";
    print '<body>' . "\n";
    print '<form action="assign1.cgi" method="get" name="entrees">' . "\n";
    print '<table style="form">' . "\n";
    print '<tr>' . "\n";
    print '<td class="label">Entrees: </td>' . "\n";
    print '<td class="value">' . "\n";
    print '<select name="entree">' . "\n";
    print '<option value="spaghetti">Spaghetti ($8.95)</option>' . "\n";
    print '<option value="lasagna">Lasanga ($9.95)</option>' . "\n";
    print '<option value="pizza">Pizza ($10.95)</option>' . "\n";
    print '</select>' . "\n";
    print '</tr><tr>' . "\n";
    print '<td class="label">Add a Salad? </td>' . "\n";
    print '<td class="value"><input type="checkbox" name="salad" /></td>'."\n";
    print '</tr><tr>' . "\n";
    print '<td class="label">Quantity: </td>' . "\n";
    print '<td class="value">';
    print '<input type="text" name="qty" size="6" maxlength="2" />' . "\n";
    print '</td>' . "\n";
    print '</tr><tr>' . "\n";
    print '<td class="label">Add more? </td>' . "\n";
    print '<td class="value"><input type="checkbox" name="more" /></td>' ."\n";
    print '</tr><tr>' . "\n";
    print '<td align="center" colspan="2">';
    print '<input type="submit" name="go" value="Submit" />';
    print '</td>' . "\n";
    print '</table>' . "\n";
    print '<input type="hidden" name="file" value="entree">' . "\n";
    print '<input type="hidden" name="session_id" value="' . $session_id
                                                           . '">' . "\n";
    print '</form>' . "\n";
    print '</body>' . "\n";
    print '</html>' . "\n";

    return;
}

sub write_drinks {
    # get the session id...
    my $session_id = shift @_;

    # this will have an error message if one was passed, and will be
    # undefined otherwise
    my $errmsg = shift @_;
    
    # ...and write the page
    print "Content-Type: text/html";
    print "\n\n";
    print '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
    print '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ';
    print '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' . "\n";
    print '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">' . "\n";
    print '<head>' . "\n";
    print '<link rel="StyleSheet" href="css/assign1.css" type="text/css" ';
    print 'media="screen" title="mystyle" />' . "\n";
    print '<title>Restaurant Bill Calculator - Drinks</title>' . "\n";
    print '</head>' . "\n";
    print '<body>' . "\n";
    print '<form action="assign1.cgi" method="get" name="drinks">' . "\n";
    if (defined $errmsg) {
        print '<div class="error">' . $errmsg . '</div>' . "\n";
    }
    print '<table style="form">' . "\n";
    print '<tr>' . "\n";
    print '<td class="label">Drinks: </td>' . "\n";
    print '<td class="value">' . "\n";
    print '<select name="drink">' . "\n";
    print '<option value="soft drink">Soft Drink ($2)</option>' . "\n";
    print '<option value="Beer">Beer ($3)</option>' . "\n";
    print '<option value="Liquor">Liquor ($3.50)</option>' . "\n";
    print '<option value="Wine">Wine ($4)</option>' . "\n";
    print '</select>' . "\n";
    print '</tr><tr>' . "\n";
    print '<td class="label">Quantity: </td>' . "\n";
    print '<td class="value">';
    print '<input type="text" name="qty" size="6" maxlength="2" />' . "\n";
    print '</td>' . "\n";
    print '</tr><tr>' . "\n";
    print '<td class="label">Add more? </td>' . "\n";
    print '<td class="value"><input type="checkbox" name="more" /></td>' ."\n";
    print '</tr><tr>' . "\n";
    print '<td align="center" colspan="2">';
    print '<input type="submit" name="go" value="Submit" />';
    print '</td>' . "\n";
    print '</table>' . "\n";
    print '<input type="hidden" name="file" value="drink">' . "\n";
    print '<input type="hidden" name="session_id" value="' . $session_id
                                                           . '">' . "\n";
    print '</form>' . "\n";
    print '</body>' . "\n";
    print '</html>' . "\n";

    return;
}

# returns the number of patrons, and the errorcode
sub process_patron {
    # put the query string into something we can work with
    my $qs = $_[0];
    my $err = 0;
    if (! $qs->{'patrons'} || length $qs->{'patrons'} > 2) {
        $err = 1;
    }
    
    return $qs->{'patrons'}, $err;
}

sub process_appetizer {
    # again with the query string
    my $qs = shift @_;
    # more contains 'on' if it was checked
    my $more = ($qs->{'more'}) ? 1 : 0;
    
    # fill %ret with the return values
    my %ret = (
       appetizer    => $qs->{'appetizer'},
       qty          => $qs->{'qty'},
       more         => $more,
    );
   
    return %ret;
}
   
sub process_entree {
    # get the QS
    my $qs = shift @_;

    # contains 'on' if it was checked
    my $more  = ($qs->{'more'})  ? 1 : 0;
    my $salad = ($qs->{'salad'}) ? 1 : 0;

    # fill ret with the appropriate values
    my %ret = (
       entree   => $qs->{'entree'},
       qty      => $qs->{'qty'},
       more     => $more,
       salad    => $salad
    );

    return %ret;
}
   
sub process_drinks {
    # get the query string
    my $qs = shift @_;

    # more contains 'on' if it was checked
    my $more = ($qs->{'more'}) ? 1 : 0;

    # fill %ret with the return values
    my %ret = (
       drink    => $qs->{'drink'},
       qty      => $qs->{'qty'},
       more     => $more
    );

    return %ret;
}
 
sub main {
    my %qs= split(/[;&=]/,$ENV{QUERY_STRING});
    foreach (values(%qs)) {
        s/(%[0-9a-f]{2}|\+)/$1 eq '+'?' ': chr(hex(substr($1,1)))/gei;
    }

    # initialize a few variables    
    my $page = $qs{'file'};
    my $err = 0;
    my $filename = "";
    my $errmsg = "";

    # if its the patron page, generate a new session id
    # otherwise, get the session id
    my $session_id;
    my %vars;
    if (! defined $qs{'session_id'} ) {
        $session_id = int(rand(100)) . time();
    }
    else {
        $session_id = $qs{'session_id'};
        $filename = ".meal-" . $session_id;
        print STDERR "Retrieving old data...\n";
        %vars = read_hash($filename);
    }

    # this is the big important variable. it holds all the information
    # from the forms.

    # this is a switch statement
    for ($page) {
        if (/patron/) {
            ($vars{'patrons'}, $err) = process_patron(\%qs);
            if (! $err) {
                write_appetizer($session_id);
            }
            else {
                $errmsg = "Number of patrons must be between 1 and 99";
                # needs error message
                write_start($errmsg);
            }
        }
        elsif (/appetizer/) {
            # validate the appetizer page
            my %ret = process_appetizer(\%qs);
            my $amt = 0;

            # if this isn't the first time through the appetizers page
            # get the total number of appetizers ordered already...
            if (defined $vars{'appetizers'}) {
                foreach my $key (keys %{ $vars{'appetizers'} }) {
                    $amt += $vars{'appetizers'}->{$key};
                }
            }
            # ...and add the number of appetizers ordered on this iteration
            $amt += $ret{'qty'};

            # if there are more appetizers than people, give an error...
            if ($amt > $vars{'patrons'}) {
                $errmsg = "Total quantity of appetizers must be between"
                           . " 0 and " . $vars{'patrons'};
                write_appetizer($session_id, $errmsg);
            }
            # ...otherwise, save the data and display the appropriate page
            else {
                # these are just for syntactical simplicity
                my $key = $ret{'appetizer'};
                my $qty = $ret{'qty'};
                # if the appetizers reference isn't there...
                if (! defined $vars{'appetizers'}) {
                    # ...create it...
                    $vars{'appetizers'} = {};
                    # ...and initialize it
                    $vars{'appetizers'}->{'garlic bread'}   = 0;
                    $vars{'appetizers'}->{'brushetta'}      = 0;
                    $vars{'appetizers'}->{'hummus'}         = 0;
                }

                # save the appetizer data
                $vars{'appetizers'}->{$key} += $qty;
                
                # if they want to add more appetizers...
                if ($ret{'more'} == 1) {
                    # ...write out the appetizer page
                    write_appetizer($session_id);
                }
                # otherwise...
                else {
                    # write out the entree page
                    write_entree($session_id);
                }
            }
        }
        elsif (/entree/) {
            # validate the entree data
            my %ret = process_entree(\%qs);
            my $amt = 0;
            
            # if this isn't the first time through the entree page
            # total up the amount of entrees ordered so far...
            if (defined $vars{'entrees'}) {
                foreach my $key (keys %{ $vars{'entrees'} }) {
                    $amt += $vars{'entrees'}->{$key};
                }
            }
            # ...and add the amount ordered in this iteration
            $amt += $ret{'qty'};

            # if the amount of entrees is not the same as number of patrons
            # and they are not going to add more...
            if ($amt != $vars{'patrons'} && $ret{'more'} == 0) {
                # give 'em a nice error message and send 'em back.
                $errmsg = "Total number of entrees must be"
                          . $vars{'patrons'};
                write_entree($session_id, $errmsg);
            }
            else {
                # for simplicity
                my $key = $ret{'entree'};
                my $qty = $ret{'qty'};

                # if the entree hash in not defined,
                if (! defined $vars{'entrees'}) {
                    # declare it...
                    $vars{'entrees'} = {};
                    # and initialize it
                    $vars{'entrees'}->{'salads'}    = 0;
                    $vars{'entrees'}->{'spaghetti'} = 0;
                    $vars{'entrees'}->{'lasagna'}   = 0;
                    $vars{'entrees'}->{'pizza'}     = 0;
                }

                # save the data
                $vars{'entrees'}->{$key} += $qty;
                $vars{'entrees'}->{'salads'} += $qty * $ret{'salad'};
                
                # if they want to add more, write out the entree page
                if ($ret{'more'} == 1) {
                    write_entree($session_id);
                }
                # otherwise, write out the drinks page
                else {
                    write_drinks($session_id);
                }
            }
        }
        elsif (/drink/) {
        }
        elsif (/subtotal/) {
        }
        elsif (/total/) {
            # WE NEED TO GET RID OF THE FILE HERE
        }
    }

    # write the vars out to the file, whee.
    $filename = ".meal-" . $session_id;
    write_hash($filename, \%vars);
}

main();