ispman/lib/CGI/Session DB_File.pm,1.1,1.2 File.pm,1.1,1.2 MySQL.pm,1.1,1.2

Joerg Delker <[email protected]>
Newsgroups gmane.comp.isp.ispman.cvs
Message-ID <[email protected]>
Update of /cvsroot/ispman/ispman/lib/CGI/Session
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv19629/Session

Modified Files:
	DB_File.pm File.pm MySQL.pm 
Log Message:
updated CGI::Session


Index: DB_File.pm
===================================================================
RCS file: /cvsroot/ispman/ispman/lib/CGI/Session/DB_File.pm,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- DB_File.pm	30 May 2002 16:24:22 -0000	1.1
+++ DB_File.pm	7 Jul 2004 20:18:54 -0000	1.2
@@ -1,183 +1,168 @@
 package CGI::Session::DB_File;
 
+# $Id$
+
 use strict;
-use vars qw($VERSION);
-use base qw(CGI::Session CGI::Session::MD5);
+use base qw(
+    CGI::Session
+    CGI::Session::ID::MD5
+    CGI::Session::Serialize::Default
+);
 
-use File::Spec;
-use Data::Dumper;
-use Fcntl qw(:DEFAULT :flock);
 use DB_File;
+use File::Spec;
+use Fcntl (':DEFAULT', ':flock');
 
-$VERSION = "2.4";
-
+# Load neccessary libraries below
 
-# do not use any indentation
-$Data::Dumper::Indent = 0;
+use vars qw($VERSION $FILE_NAME);
+$FILE_NAME = 'cgisess.db';
 
-sub retrieve {
-    my ($self, $sid, $options) = @_;
+$VERSION = '0.1';
 
-    my $file    = $options->{FileName};
-    my $lckdir  = $options->{LockDirectory};
+sub store {
+    my ($self, $sid, $options, $data) = @_;
 
-	my $lckfile = File::Spec->catfile($lckdir, "CGI-Session-$sid.lck");
-	sysopen (LCK, $lckfile, O_RDWR|O_CREAT, 0664) 
-		or $self->error("Couldn't create lockfile $lckfile, $!"), return;
-	flock (LCK, LOCK_SH) 
-		or $self->error("Couldn't lock $lckfile	, $!"), return;
+    my $storable_data = $self->freeze($data);
 
-    tie my %session, "DB_File", $file, O_RDWR|O_CREAT, 0777 
-		or $self->error("Couldn't open $file, $!"), return;
+    my $args = $options->[1];
+    my $file = File::Spec->catfile($args->{Directory}, $args->{FileName} || $FILE_NAME);
 
-    my $tmp = $session{$sid} or $self->error("Session ID '$sid' doesn't exist"), return;
-    
-	untie %session;
-	close (LCK);
+    tie my %db, "DB_File", $file, O_RDWR|O_CREAT, 0644 or die $!;
+    $db{$sid} = $storable_data;
+    untie(%db) or die $!;
 
-	my $data = {};	eval $tmp;
+    return 1;
 
-	return $data;
 }
 
 
+sub retrieve {
+    my ($self, $sid, $options) = @_;
 
+    # you will need to retrieve the stored data, and
+    # deserialize it using $self->thaw() method
 
+    my $args = $options->[1];
+    my $file = File::Spec->catfile($args->{Directory}, $args->{FileName} || $FILE_NAME);
 
-sub store {
-    my ($self, $sid, $hashref, $options) = @_;
+    tie my %db, "DB_File", $file, O_RDWR|O_CREAT, 0644 or die $!;
+    my $data = $self->thaw($db{$sid});
+    untie(%db);
 
-    my $file    = $options->{FileName};
-    my $lckdir  = $options->{LockDirectory};
+    return $data;
+}
 
-	my $lckfile = File::Spec->catfile($lckdir, "CGI-Session-$sid.lck");
-	sysopen (LCK, $lckfile, O_RDWR|O_CREAT, 0664) or $self->error("Couldn't create lockfile $lckfile, $!"), return;
-	flock (LCK, LOCK_EX) 
-		or $self->error("Couldn't lock $lckfile, $!"), return;
-	
-    tie my %session, "DB_File", $file, O_RDWR|O_CREAT, 0777 
-		or $self->error("Couldn't open $file: $!"), return;
-	
-	my $d = Data::Dumper->new([$hashref], ["data"]);
-    
-	$session{$sid} = $d->Dump();
-    
-	untie %session;
-	close (LCK);
+
+
+sub remove {
+    my ($self, $sid, $options) = @_;
+
+    # you simply need to remove the data associated
+    # with the id
+
+    my $args = $options->[1];
+    my $file = File::Spec->catfile($args->{Directory}, $args->{FileName} || $FILE_NAME);
+    tie my %db, "DB_File", $file, O_RDWR|O_CREAT, 0644 or die $!;
+    delete $db{$sid};
+    untie(%db) or die $!;
 
     return 1;
-}
 
 
+}
 
-sub tear_down {
-	my ($self, $sid, $options) = @_;
-	
-	my $file = $options->{FileName};
-	my $lckdir = $options->{LockDirectory};
 
-	tie (my %session, "DB_File", $file) or die $!;
-	delete $session{$sid};
-	untie %session;
 
+sub teardown {
+    my ($self, $sid, $options) = @_;
+
+    # this is called just before session object is destroyed
 }
 
+
+
+
+# $Id$
+
 1;
 
 =pod
 
 =head1 NAME
 
-CGI::Session::DB_File - Driver for CGI::Session class
+CGI::Session::DB_File - DB_File driver for CGI::Session
 
 =head1 SYNOPSIS
 
-	use constant COOKIE => "TEST_SID";	# cookie to store the session id
+    use CGI::Session;
+    $session = new CGI::Session("driver:DB_File", undef, {Directory=>'/tmp'});
 
-	use CGI::Session::DB_File;
-	use CGI;
+For more details, refer to L<CGI::Session> manual
 
-	my $cgi = new CGI;
+=head1 DESCRIPTION
 
-	# getting the 
-	my $c_sid = $cgi->cookie(COOKIE) || undef;
-	
-	my $session = new CGI::Session::DB_File($c_sid, 
-		{
-			LockDirectory	=>'/tmp/locks', 
-			FileName		=> '/tmp/sessions.db'
-		});
-	
-	# now let's create a sid cookie and send it to the client's browser.
-	# if it is an existing session, it will be the same as before,
-	# but if it's a new session, $session->id() will return a new session id.
-	{
-		my $new_cookie = $cgi->cookie(-name=>COOKIE, -value=>$session->id);
-		print $cgi->header(-cookie=>$new_cookie);
-	}
+CGI::Session::DB_File is a CGI::Session driver to store session data in BerkeleyDB.
+Filename to store the session data is by default 'cgisess.db'. If you want different
+name, you can either specify it with the "FileName" option as below:
 
-	print $cgi->start_html("CGI::Session::File");
+    $s = new CGI::Session::DB_File(undef, {Directory=>'/tmp', FileName=>'sessions.db'});
 
-	# assuming we already saved the users first name in the session
-	# when he visited it couple of days ago, we can greet him with
-	# his first name
+or by setting the value of the $CGI::Session::DB_File::NAME variable before creating
+the session object:
 
-	print "Hello", $session->param("f_name"), ", how have you been?";
+    $CGI::Session::DB_File::NAME = 'sessions.db';
+    $s = new CGI::Session("driver:DB_File", undef, {Directory=>'/tmp'});
 
-	print $cgi->end_html();
+The only driver option required, as in the above examples, is "Directory", which tells the
+driver where the session file and lock files should be created.
 
-=head1 DESCRIPTION
+"FileName" option is also available, but not required.
 
-C<CGI::Session::DB_File> is the driver for C<CGI::Session> to store and retrieve
-the session data in and from the Berkeley DB 1.x. To be able to write your own
-drivers for the L<CGI::Session>, please consult L<developer section|CGI::Session/DEVEROPER SECTION>
-of the L<manual|CGI::Session>.
+=head1 COPYRIGHT
 
-Constructor requires two arguments, as all other L<CGI::Session> drivers do.
-The first argument has to be session id to be initialized (or undef to tell
-the L<CGI::Session>  to create a new session id). The second argument has to be
-a reference to a hash with two following require key/value pairs:
+Copyright (C) 2001-2002 Sherzod Ruzmetov. All rights reserved.
 
-=over 4
+This library is free software and can be modified and distributed under the same
+terms as Perl itself.
 
-=item C<Filename>
+Bug reports should be directed to [email protected], or posted to [email protected]
+mailing list.
 
-path to a file where all the session data will be stored
+=head1 AUTHOR
 
-=item C<LockDirectory>
+CGI::Session::DB_File is written and maintained by Sherzod Ruzmetov <[email protected]>
 
-path in the file system where all the lock files for the sessions will be stored
+=head1 SEE ALSO
 
-=back
+=over 4
 
-C<CGI::Session::DB_File> uses L<Data::Dumper|Data::Dumper> to serialize the session data
-before storing it in the session file. 
+=item *
 
-=head2 Example
-	
-	# get the sessino id either from the SID cookie, or from
-	# the sid parameter in the URL
-	my $c_sid = $cgi->cookie("SID") || $cgi->param("sid") || undef;
-	my $session = new CGI::Session::DB_File($c_sid, 
-		{
-			LockDirectory=>'/tmp', 
-			FileName=>'/tmp/sessions.db'
-		});
+L<CGI::Session|CGI::Session> - CGI::Session manual
 
-For more extensive examples of the C<CGI::Session> usage, please refer to L<CGI::Session manual|CGI::Session>
+=item *
 
-=head1 AUTHOR
+L<CGI::Session::Tutorial|CGI::Session::Tutorial> - extended CGI::Session manual
 
-Sherzod B. Ruzmetov <[email protected]>
+=item *
 
-=head1 COPYRIGHT
+L<CGI::Session::CookBook|CGI::Session::CookBook> - practical solutions for real life problems
 
-This library is free software and can be redistributed under the same
-conditions as Perl itself.
+=item *
 
-=head1 SEE ALSO
+B<RFC 2965> - "HTTP State Management Mechanism" found at ftp://ftp.isi.edu/in-notes/rfc2965.txt
 
-L<CGI::Session>, L<CGI::Session::File>, L<CGI::Session::DB_File>,
-L<CGI::Session::MySQL>, L<Apache::Session>
+=item *
+
+L<CGI|CGI> - standard CGI library
+
+=item *
+
+L<Apache::Session|Apache::Session> - another fine alternative to CGI::Session
+
+=back
 
 =cut
+
+# $Id$

Index: File.pm
===================================================================
RCS file: /cvsroot/ispman/ispman/lib/CGI/Session/File.pm,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- File.pm	30 May 2002 16:24:22 -0000	1.1
+++ File.pm	7 Jul 2004 20:18:54 -0000	1.2
@@ -1,204 +1,190 @@
 package CGI::Session::File;
 
-use strict;
-use vars qw($VERSION);
-use Carp;
-use base qw(CGI::Session CGI::Session::MD5);
+# $Id$
 
+use strict;
 use File::Spec;
-use Fcntl qw(:DEFAULT :flock);
-use Data::Dumper;
+use Fcntl (':DEFAULT', ':flock');
+use base qw(
+    CGI::Session
+    CGI::Session::ID::MD5
+    CGI::Session::Serialize::Default
+);
 
-# do not use any indentation
-$Data::Dumper::Indent = 0;
-$VERSION = "2.4";
+use vars qw($FileName $VERSION);
 
+($VERSION) = '$Revision$' =~ m/Revision:\s*(\S+)/;
+$FileName = 'cgisess_%s';
 
-# constructor is inherited from CGI::Session
-sub retrieve {
-    my ($self, $sid, $options) = @_;
+sub store {
+    my ($self, $sid, $options, $data) = @_;
 
-    # getting the options passed to the constructor
-    my $dir     = $options->{Directory};
-    my $lckdir  = $options->{LockDirectory};
+    $self->File_init($sid, $options);
+    unless ( sysopen (FH, $self->{_file_path}, O_RDWR|O_CREAT|O_TRUNC, 0644) ) {
+        $self->error("Couldn't store $sid into $self->{_file_path}: $!");
+        return undef;
+    }
+    unless (flock(FH, LOCK_EX) ) {
+        $self->error("Couldn't get LOCK_EX: $!");
+        return undef;
+    }
+    print FH $self->freeze($data);    
+    unless ( close(FH) ) {
+        $self->error("Couldn't close $self->{_file_path}: $!");
+        return undef;
+    }
+    return 1;
+}
 
-	unless ( $dir && $lckdir ) {
-		my $class = ref($self);
-		croak "Usage: $class->new(\$sid, {Directory=>'/some/dir', LockDirectory=>'/some/dir'})";
-	}
 
-    # creating an OS independant path to the session file and the lockfile
-    my $file    = File::Spec->catfile($dir, "CGI-Session-$sid.dat");
-    my $lckfile =File::Spec->catfile($lckdir, "CGI-Session-$sid.lck");
+sub retrieve {
+    my ($self, $sid, $options) = @_;
 
-    # opening the lockfile
-    sysopen(LCK, $lckfile, O_RDWR|O_CREAT, 0644) or $self->error("Couldn't create lockfile, $!"), return;
-    flock(LCK, LOCK_SH) or $self->error("Couldn't acquire lock on $lckfile, $!"), return;
+    $self->File_init($sid, $options);
 
-	
-    # getting the data from the session file
-    local ( $/, *FH );
-    sysopen(FH, $file, O_RDONLY) or $self->error("Couldn't open data file ($file), $!"), return;
-    my $tmp = <FH>;
-    close (FH); close (LCK);
+    # If the session data does not exist, return.
+    unless ( -e $self->{_file_path} ) {
+        return undef;
+    }
+    
+    unless ( sysopen(FH, $self->{_file_path}, O_RDONLY) ) {
+        $self->error("Couldn't open $self->{_file_path}: $!");
+        return undef;
+    }
+    unless (flock(FH, LOCK_SH) ) {
+        $self->error("Couldn't lock the file: $!");
+        return undef;
+    }
+    my $data = undef;
+    $data .= $_ while <FH>;
+    
+    close(FH);
+    return $self->thaw($data);
+}
 
-    # intializing the hashref
-    my $data = {}; eval $tmp;
 
-    # did something go wrong?
-    if ( $@ ) { $self->error("Couldn't eval() the data, $!"), return }
 
-    # returning the eval()ed data
-    return $data;
+sub remove {
+    my ($self, $sid, $options) = @_;
+    
+    $self->File_init($sid, $options);
+    unless ( unlink ( $self->{_file_path} ) ) {
+        $self->error("Couldn't unlink $self->{_file_path}: $!");
+        return undef;
+    }
+    return 1;
 }
 
 
-sub store {
-    my ($self, $sid, $hashref, $options) = @_;
 
-    # getting the options passed to the constructor
-    my $dir     = $options->{Directory};
-    my $lckdir  = $options->{LockDirectory};
+sub teardown {
+    my ($self, $sid, $options) = @_;
 
-    # creating an OS independant path
-    my $file    = File::Spec->catfile($dir, "CGI-Session-$sid.dat");
-    my $lckfile = File::Spec->catfile($lckdir, "CGI-Session-$sid.lck");
-	
+    return 1;
+}
 
-    # opening the lockfile
-    sysopen (LCK, $lckfile, O_RDWR|O_CREAT, 0664) or $self->error("Couldn't open $lckfile, $!"), return;
-    flock(LCK, LOCK_EX) or $self->error("Couldn't acquire lock on $lckfile, $!"), return;
 
-    # storing the data in the session file
-    local (*FH);
-    sysopen (FH, $file, O_RDWR|O_CREAT|O_TRUNC, 0664) or $self->error("Couldn't create $file, $!"), return;
 
-    # creating a Data::Dumper object of $hashref
-    my $d = Data::Dumper->new([$hashref], ["data"]);
 
-    # dumping the $hashref into a session file
-    print FH $d->Dump();
-    close (FH); close LCK;
+sub File_init {
+    my ($self, $sid, $options) = @_;
 
-    return 1;
+    my $dir = $options->[1]->{Directory};
+    my $path = File::Spec->catfile($dir, sprintf("$FileName", $sid));
+    $self->{_file_path} = $path;    
 }
 
 
-sub tear_down {
-    my ($self, $sid, $options) = @_;
-
-    # getting the options passed to the constructor
-    my $dir = $options->{Directory};
-
-    # discovering the session filename
-    my $file = File::Spec->catfile($dir, "CGI-Session-$sid.dat");
 
-    # deleting the file
-    unlink $file or $self->error("Couldn't delete the session data $file: $!"), return;
 
-    return 1;
-}
 
 
+# $Id$
 
-1;
+1;       
 
 =pod
 
 =head1 NAME
 
-CGI::Session::File - CGI::Session driver for
+CGI::Session::File - Default CGI::Session driver
+
+=head1 REVISION
+
+This manual refers to $Revision$
 
 =head1 SYNOPSIS
+    
+    use CGI::Session;
+    $session = new CGI::Session("driver:File", undef, {Directory=>'/tmp'});
 
-	use constant COOKIE => "TEST_SID";	# cookie to store the session id
+For more examples, consult L<CGI::Session> manual
 
-	use CGI::Session::File;
-	use CGI;
+=head1 DESCRIPTION
 
-	my $cgi = new CGI;
+CGI::Session::File is a default CGI::Session driver. Stores the session data
+in plain files. For the list of available methods, consult L<CGI::Session> manual.
 
-	# getting the session id from the cookie
-	my $c_sid = $cgi->cookie(COOKIE) || undef;
-	
-	my $session = new CGI::Session::File($c_sid, 
-		{
-			LockDirectory	=>'/tmp/locks', 
-			Directory		=>'/tmp/sessions'
-		});
-	
-	# now let's create a sid cookie and send it to the client's browser.
-	# if it is an existing session, it will be the same as before,
-	# but if it's a new session, $session->id() will return a fresh one
-	{
-		my $new_cookie = $cgi->cookie(-name=>COOKIE, -value=>$session->id);
-		print $cgi->header(-cookie=>$new_cookie);
-	}
+Each session is stored in a seperate file. File name is by default formatted as "cgisess_%s",
+where '%s' is replaced with the effective session id. To change file name formatting,
+update $CGI::Session::File::NAME variable. Examples:
 
-	print $cgi->start_html("CGI::Session::File");
+    $CGI::Session::File::FileName = 'cgisess_%s.dat';       # with .dat extention
+    $CGI::Session::File::FileName = '%s.session';
+    $CGI::Session::File::FileName = '%CGI-Session-%s.dat';  # old style
 
-	# assuming we already saved the users first name in the session
-	# when he visited it couple of days ago, we can greet him with
-	# his first name
+The only driver option required is 'Directory', which denotes the location 
+session files are stored in.
 
-	print "Hello", $session->param("f_name"), ", how have you been?";
+Example:
 
-	print $cgi->end_html();
+    $session = new CGI::Session("driver:File", undef, {Directory=>'some/directory'});
 
-=head1 DESCRIPTION
+=head1 COPYRIGHT
 
-C<CGI::Session::File> is the driver for the L<CGI::Session|CGI::Session> to store and retrieve
-the session data in and from the plain text files. To be able to write your own
-drivers for the L<CGI::Session|CGI::Session>, please consult L<developer section|CGI::Session/DEVELOPER SECTION>
-of the L<manual|CGI::Session>
+Copyright (C) 2001-2002 Sherzod Ruzmetov. All rights reserved.
 
-Constructor requires two arguments, as all other L<CGI::Session> drivers do.
-The first argument has to be session id to be initialized (or undef to tell
-the CGI::Session  to create a new session id). The second argument has to be
-a reference to a hash with two following require key/value pairs:
+This library is free software and can be modified and distributed under the same
+terms as Perl itself. 
 
-=over 4
+Bug reports should be directed to [email protected], or posted to [email protected]
+mailing list.
 
-=item C<Directory>
+=head1 AUTHOR
 
-path in the file system where all the session data will be stored
+CGI::Session::File is written and maintained by Sherzod Ruzmetov <[email protected]>
 
-=item C<LockDirectory>
+=head1 SEE ALSO
 
-path in the file system where all the lock files for the sessions will be stored
+=over 4
 
-=back
+=item *
 
-C<CGI::Session::File> uses L<Data::Dumper|Data::Dumper> to serialize the session data
-before storing it in the session file. 
+L<CGI::Session|CGI::Session> - CGI::Session manual
 
-=head2 Example
-	
-	# get the sessino id either from the SID cookie, or from
-	# the sid parameter in the URL
-	my $c_sid = $cgi->cookie("SID") || $cgi->param("sid") || undef;
-	my $session = new CGI::Session::File($c_sid, 
-		{
-			LockDirectory => '/tmp', 
-			Directory	  => '/tmp'
-		});
+=item *
 
-For more extensive examples of the L<CGI::Session|CGI::Session> usage, please refer to 
-L<CGI::Session> manual.
+L<CGI::Session::Tutorial|CGI::Session::Tutorial> - extended CGI::Session manual
 
-=head1 AUTHOR
+=item *
 
-Sherzod B. Ruzmetov <[email protected]>
+L<CGI::Session::CookBook|CGI::Session::CookBook> - practical solutions for real life problems
 
-=head1 COPYRIGHT
+=item *
 
-This library is free software and can be redistributed under the same
-conditions as Perl itself.
+B<RFC 2965> - "HTTP State Management Mechanism" found at ftp://ftp.isi.edu/in-notes/rfc2965.txt
 
-=head1 SEE ALSO
+=item *
 
-L<CGI::Session>, L<CGI::Session::File>, L<CGI::Session::DB_File>,
-L<CGI::Session::MySQL>, L<Apache::Session>
+L<CGI|CGI> - standard CGI library
+
+=item *
+
+L<Apache::Session|Apache::Session> - another fine alternative to CGI::Session
+
+=back
 
 =cut
 
+
+# $Id$

Index: MySQL.pm
===================================================================
RCS file: /cvsroot/ispman/ispman/lib/CGI/Session/MySQL.pm,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- MySQL.pm	30 May 2002 16:24:22 -0000	1.1
+++ MySQL.pm	7 Jul 2004 20:18:54 -0000	1.2
@@ -1,103 +1,114 @@
 package CGI::Session::MySQL;
 
+# $Id$
+
 use strict;
-use vars qw($VERSION $TABLE_NAME);
-use base qw(CGI::Session CGI::Session::MD5);
+# Inheriting necessary functionalities from the 
+# following libraries. Do not change it unless you know
+# what you are doing
+use base qw(
+    CGI::Session
+    CGI::Session::ID::MD5
+    CGI::Session::Serialize::Default
+);
 
-use Data::Dumper;
-use Carp;
-eval "require DBI";
 
-if ( $@ ) {
-	$CGI::Session::errstr = $@;
-}
+# driver specific libraries should go below
 
-$VERSION = "2.3";
+use vars qw($VERSION $TABLE_NAME);
 
-# chose the most compat from of serialization in Data::Dumper
-$Data::Dumper::Indent = 0;
+($VERSION) = '$Revision$' =~ m/Revision:\s*(\S+)/;
 
-# This is the sessions table. Change it if you want to 
-# use some other table for your sessions data
 $TABLE_NAME = 'sessions';
 
-# returns $dbh and $lckh
-sub MYSQL_dbh {
-	my ($self, $option) = @_;
+########################
+# Driver methods follow
+########################
 
-	my $dbh     = $option->{Handle};
-    my $lckh    = $option->{LockHandle};
-    my $dsn     = $option->{DataSource};
-    my $username= $option->{UserName};
-    my $psswd   = $option->{Password};
-    my $lcksn   = $option->{LockDataSource} || $dsn;
-    my $lckuser = $option->{LockUserName} || $username;
-    my $lckpsswd= $option->{LockPassword} || $psswd;
 
-	if ( $dbh && $lckh ) {
-		return ($dbh, $lckh);
-	}
+# stores the serialized data. Returns 1 for sucess, undef otherwise
+sub store {
+    my ($self, $sid, $options, $data) = @_;   
 
-	$dbh	= DBI->connect($dsn, $username, $psswd) or $self->error($DBI::errstr), return;
-	$lckh	= DBI->connect($lcksn, $lckuser, $lckpsswd) or $self->error($DBI::errstr), return;
+    my $dbh = $self->MySQL_dbh($options);
+    my $lck_status = $dbh->selectrow_array(qq|SELECT GET_LOCK("$sid", 10)|);
+    unless ( $lck_status == 1 ) {
+        $self->error("Couldn't acquire lock on id '$sid'. Lock status: $lck_status");
+        return undef;
+    }
 
-	return ($dbh, $lckh);
+    $dbh->do(qq|REPLACE INTO $TABLE_NAME (id, a_session) VALUES(?,?)|, 
+                undef, $sid, $self->freeze($data));
+    
+    return $dbh->selectrow_array(qq|SELECT RELEASE_LOCK("$sid")|);
 }
 
 
 
-
-
-
-
-
-
+# retrieves the serialized data and deserializes it
 sub retrieve {
-    my ($self, $sid, $option) = @_;
-
-    my ($dbh, $lckh) = $self->MYSQL_dbh($option) or return;
-	$lckh->do("LOCK TABLES $TABLE_NAME READ");
-
-    my ($tmp) = $dbh->selectrow_array(qq|SELECT a_session FROM $TABLE_NAME WHERE id=?|, undef, $sid);	
+    my ($self, $sid, $options) = @_;
 
-	$lckh->do("UNLOCK TABLES");	
-	
-	my $data = {}; eval $tmp;
+    # after you get the data, deserialize it using
+    # $self->thaw(), and return it
+    my $dbh = $self->MySQL_dbh($options);
+    my $lck_status  = $dbh->selectrow_array(qq|SELECT GET_LOCK("$sid", 10)|);
+    unless ( $lck_status == 1 ) {
+        $self->error("Couldn't acquire lock on is '$sid'. Lock status: $lck_status");
+        return undef;
+    }
 
-	if ( $@ ) {
-		$self->error("Couldn't eval() the data, $@"), return;
-	}
+    my $data = $dbh->selectrow_array(qq|SELECT a_session FROM $TABLE_NAME WHERE id=?|, undef, $sid);
+    $lck_status = $dbh->selectrow_array(qq|SELECT RELEASE_LOCK("$sid")|);
+    unless ( $lck_status == 1 ) {
+        $self->error("Couldn't release lock of '$sid'. Lock status: $lck_status");
+        return undef;
+    }
 
-	return $data;
+    return $self->thaw($data);
 }
 
 
+# removes the given data and all the disk space associated with it
+sub remove {
+    my ($self, $sid, $options) = @_;
 
+    my $dbh = $self->MySQL_dbh($options);
+    my $lck_status = $dbh->selectrow_array(qq|SELECT GET_LOCK("$sid", 10)|);
+    unless ( $lck_status == 1 ) {
+        $self->error("Couldn't acquire lock on id '$sid'. Lock status; $lck_status");
+        return undef;
+    }
 
+    $dbh->do(qq|DELETE FROM $TABLE_NAME WHERE id=?|, undef, $sid);
+    $lck_status = $dbh->selectrow_array(qq|SELECT RELEASE_LOCK("$sid")|);
+    unless ( $lck_status == 1 ) {
+        $self->error("Couldn't release lock of '$sid'. Lock status: $lck_status");
+        return undef;
+    }
+    
+    return 1;    
+}
 
 
 
 
+# called right before the object is destroyed to do cleanup
+sub teardown {
+    my ($self, $sid, $options) = @_;
 
+    my $dbh = $self->MySQL_dbh($options);
 
-sub store {
-    my ($self, $sid, $hashref, $option) = @_;
-
-	my ($dbh, $lckh) = $self->MYSQL_dbh($option);	
-    my $d = Data::Dumper->new([$hashref], ["data"]);
-    my $exists = $dbh->selectrow_array(qq|SELECT a_session FROM $TABLE_NAME WHERE id=?|, undef, $sid);
-
-	$lckh->do("LOCK TABLES $TABLE_NAME WRITE");
-
-    if ( $exists ) {		
-        my $rv = $dbh->do(qq|UPDATE $TABLE_NAME SET a_session=? WHERE id=?|, undef, $d->Dump(), $sid);
-		$lckh->do("UNLOCK TABLES");
-		return $rv;
+    # Call commit if it isn't meant to be autocommited!
+    unless ( $dbh->{AutoCommit}  ) {
+        $dbh->commit();
+    }
+    
+    if ( $self->{MySQL_disconnect} ) {
+        $dbh->disconnect();
     }
 
-    my $rv =  $dbh->do(qq|INSERT INTO $TABLE_NAME SET id=?, a_session=?|, undef, $sid, $d->Dump());
-	$lckh->do("UNLOCK TABLES");
-	return $rv;
+    return 1;
 }
 
 
@@ -105,173 +116,124 @@
 
 
 
+sub MySQL_dbh {
+    my ($self, $options) = @_;
 
+    my $args = $options->[1] || {};
+    
+    if ( defined $self->{MySQL_dbh} ) {
+        return $self->{MySQL_dbh};
 
-sub tear_down {
-    my ($self, $sid, $option) = @_;
+    }
+    
+    require DBI;
 
-	my ($dbh, $lckh) = $self->MYSQL_dbh($option);    
+    $self->{MySQL_dbh} = $args->{Handle} || DBI->connect(
+                    $args->{DataSource},
+                    $args->{User}       || undef, 
+                    $args->{Password}   || undef, 
+                    { RaiseError=>1, PrintError=>1, AutoCommit=>1 } );
 
-	$lckh->do("LOCK TABLES $TABLE_NAME WRITE");
-    my $rv =  $dbh->do(qq|DELETE FROM $TABLE_NAME WHERE id=?|, undef, $sid);  
-	$lckh->do("UNLOCK TABLES");
-	return $rv;
+    # If we're the one established the connection, 
+    # we should be the one who closes it    
+    $args->{Handle} or $self->{MySQL_disconnect} = 1;
+    return $self->{MySQL_dbh};
+    
 }
 
 
 
 
+# $Id$
 
-
-
-1;
-
-
+1;       
 =pod
 
 =head1 NAME
 
-CGI::Session::MySQL - Driver for CGI::Session class
+CGI::Session::MySQL - MySQL driver for  CGI::Session
 
 =head1 SYNOPSIS
+    
+    use CGI::Session;
+    $session = new CGI::Session("driver:MySQL", undef, {Handle=>$dbh});
 
-	use constant COOKIE => "TEST_SID";	# cookie to store the session id
-
-	use CGI::Session::MySQL;
-	use CGI;
-	use DBI;
-
-	my $dbh = DBI->connect("DBI:mysql:dev", "dev", "marley01");
-	my $cgi = new CGI;
-
-	# getting the session id from the cookie
-	my $c_sid = $cgi->cookie(COOKIE) || undef;
-	
-	my $session = new CGI::Session::MySQL($c_sid, 
-		{
-			LockHandle		=> $dbh,
-			Handle			=> $dbh
-		});
-	
-	# now let's create a sid cookie and send it to the client's browser.
-	# if it is an existing session, it will be the same as before,
-	# but if it's a new session, $session->id() will return a new session id.
-	{
-		my $new_cookie = $cgi->cookie(-name=>COOKIE, -value=>$session->id);
-		print $cgi->header(-cookie=>$new_cookie);
-	}
-
-	print $cgi->start_html("CGI::Session::MySQL");
-
-	# assuming we already saved the users first name in the session
-	# when he visited it couple of days ago, we can greet him with
-	# his first name
-
-	print "Hello", $session->param("f_name"), ", how have you been?";
-
-	print $cgi->end_html();
+For more examples, consult L<CGI::Session> manual
 
 =head1 DESCRIPTION
 
-C<CGI::Session::MySQL> is the driver for the L<CGI::Session> class to store 
-and retrieve the session data in and from the MySQL database 
-
-To be able to write your own drivers for L<CGI::Session>, please consult 
-L<CGI::Session manual|CGI::Session>.
+CGI::Session::MySQL is a CGI::Session driver to store session data in MySQL table.
+To write your own drivers for B<CGI::Session> refere L<CGI::Session> manual.
 
-Constructor requires two arguments, as all other L<CGI::Session> drivers do.
-The first argument has to be session id to be initialized (or undef to tell
-the L<CGI::Session>  to create a new session id). The second argument has to be
-a reference to a hash with two following required key/value pairs:
 
-=over 4
+=head1 STORAGE
 
-=item C<Handle>
+To store session data in MySQL database, you first need to create a suitable table for it
+with the following command:
 
-this has to be a database handler returned from the C<DBI->connect()> 
-(see L<DBI manual|DBI>, L<DBD::mysql manual|DBD::mysql>)
+    CREATE TABLE sessions (
+        id CHAR(32) NOT NULL UNIQUE,
+        a_session TEXT NOT NULL
+    );
 
-=item C<LockHandle>
 
-This is also a handler returned from the C<DBI->connect()> for locking the sessions
-table.
+You can also add any number of additional columns to the table, but the above "id"
+and "a_session" are required. 
 
-=back
+If you want to store the session data in other table than "sessions", before creating
+the session object you need to set the special variable B<$CGI::Session::MySQL::TABLE_NAME>
+to the name of the table:
 
-You can also ask C<CGI::Session::MySQL> to create a handler for you. To do this
-you will need to pass it the following key/value pairs as the second argument:
+    use CGI::Session;
 
-=over 4
+    $CGI::Session::MySQL::TABLE_NAME = 'my_sessions';
+    $session = new CGI::Session("driver:MySQL", undef, {Handle=>$dbh});
 
-=item C<DataSource>
+=head1 COPYRIGHT
 
-Name of the datasource L<DBI> has to use. Usually C<DBI:mysql:db_name>
+Copyright (C) 2001, 2002 Sherzod Ruzmetov. All rights reserved.
 
-=item C<UserName>
+This library is free software and can be modified and distributed under the same
+terms as Perl itself. 
 
-Username who is able to access the above C<DataSource>
 
-=item C<Password>
+=head1 AUTHOR
 
-Password the C<UserName> has to provide to be able to access the C<DataSource>.
+Sherzod Ruzmetov <[email protected]>. All the bug reports should be sent to the author
+to [email protected]>
 
-=back
+=head1 SEE ALSO
 
-It also expects C<LockDatasource>, C<LockUserName> and C<LockPassword> key/values,
-but if they are missing defaults to the ones provided by C<DataSource>, C<UserName> 
-and C<Password> respectively. 
+=over 4
 
-C<CGI::Session::MySQL> uses L<Data::Dumper|Data::Dumper> to serialize the session data
-before storing it in the session file. 
+=item *
 
-=head1 STORAGE
+L<CGI::Session|CGI::Session> - CGI::Session manual
 
-Since the data should be stored in the mysql table, you will first need to
-create a sessions table in your mysql database. The following command should
-suffice for basic use of the library:
+=item *
 
-	CREATE TABLE sessions (
-		id CHAR(32) NOT NULL PRIMARY KEY,
-		a_session TEXT
-	);
+L<CGI::Session::Tutorial|CGI::Session::Tutorial> - extended CGI::Session manual
 
-=head1 Example
-	
-	# get the sessino id either from the SID cookie, or from
-	# the sid parameter in the URL
-	my $c_sid = $cgi->cookie("SID") || $cgi->param("sid") || undef;
-	my $session = new CGI::Session::MySQL($c_sid, 
-		{
-			Handle => $dbh,
-			LockHandle => $dbh
-		});
+=item *
 
-For more extensive examples of the L<CGI::Session> usage, please refer to 
-the L<manual|CGI::Session>
+L<CGI::Session::CookBook|CGI::Session::CookBook> - practical solutions for real life problems
 
-=head1 BUGS
+=item *
 
-Currently no bugs have been detected, but eval() in retrive() method
-produces the following error:
+B<RFC 2965> - "HTTP State Management Mechanism" found at ftp://ftp.isi.edu/in-notes/rfc2965.txt
 
-	Use of uninitialized value in string at blib/lib/CGI/Session/MySQL.pm line 65.
+=item *
 
-Of which I am quite embarrased. Coulld not figure out how to get rid of it.
-So if you can think of any solution, please take this guilt off my conscious
-ASAP.
+L<CGI|CGI> - standard CGI library
 
-=head1 AUTHOR
+=item *
 
-Sherzod B. Ruzmetov <[email protected]>
+L<Apache::Session|Apache::Session> - another fine alternative to CGI::Session
 
-=head1 COPYRIGHT
+=back
 
-This library is free software and can be redistributed under the same
-conditions as Perl itself.
+=cut
 
-=head1 SEE ALSO
 
-L<CGI::Session>, L<CGI::Session::File>, L<CGI::Session::DB_File>,
-L<CGI::Session::MySQL>, L<Apache::Session>
 
-=cut
+# $Id$



-------------------------------------------------------
This SF.Net email sponsored by Black Hat Briefings & Training.
Attend Black Hat Briefings & Training, Las Vegas July 24-29 - 
digital self defense, top technical experts, no vendor pitches, 
unmatched networking opportunities. Visit www.blackhat.com
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.