Example 6-18 shows the original script's code.

Example 6-18. cookie_script.pl

use strict;
use CGI;
use CGI::Cookie;
use vars qw($q $switch $status $sessionID);

init( );
print_header( );
print_status( );

sub init {
    $q = new CGI;
    $switch = $q->param("switch") ? 1 : 0;
    my %cookies = CGI::Cookie->fetch;
    $sessionID = exists $cookies{'sessionID'} 
        ? $cookies{'sessionID'}->value
        : '';

    # 0 = not running, 1 = running
    $status = $sessionID ? 1 : 0;
    # switch status if asked to
    $status = !$status if $switch;

    if ($status) {
        # preserve sessionID if it exists or create a new one
        $sessionID ||= generate_sessionID( ) if $status;
    } else {
        # delete the sessionID
        $sessionID = '';

sub print_header {
    my $c = CGI::Cookie->new(
         -name    => 'sessionID',
         -value   => $sessionID,
         -expires => '+1h'

    print $q->header(
         -type   => 'text/html',
         -cookie => $c

# print the current Session status and a form to toggle the status
sub print_status {
    print qq{<html><head><title>Cookie</title></head><body>};

    print "<B>Status:</B> ",
          ? "Session is running with ID: $sessionID"
          : "No session is running";
    # change status form
    my $button_label = $status ? "Stop" : "Start";
    print qq{<hr>
         <input type=submit name=switch value=" $button_label "> 
    print qq{</body></html>};

# A dummy ID generator
# Replace with a real session ID generator
sub generate_sessionID {
    return scalar localtime;

The code is very simple. It creates a session when you press the Start button and deletes it when you pressed the Stop button. The session is stored and retrieved using cookies.

We have split the code into three subroutines. init( ) initializes global variables and parses incoming data. print_header( ) prints the HTTP headers, including the cookie header. Finally, print_status( ) generates the output. Later, we will see that this logical separation will allow an easy conversion to Perl content-handler code.

We have used a few global variables, since we didn't want to pass them from function to function. In a big project, you should be very restrictive about what variables are allowed to be global, if any. In any case, the init( ) subroutine makes sure all these variables are reinitialized for each code reinvocation.

We have used a very simple generate_sessionID( ) function that returns a current date-time string (e.g., Wed Apr 12 15:02:23 2000) as a session ID. You'll want to replace this with code that generates a unique and unpredictable session ID each time it is called.