[Jifty-commit] r1668 - in jifty/trunk: lib/Jifty/Web
lib/Jifty/Web/Session
jifty-commit at lists.jifty.org
jifty-commit at lists.jifty.org
Tue Jul 25 15:59:59 EDT 2006
Author: audreyt
Date: Tue Jul 25 15:59:57 2006
New Revision: 1668
Added:
jifty/trunk/lib/Jifty/Web/Session/
jifty/trunk/lib/Jifty/Web/Session/ClientSide.pm
Modified:
jifty/trunk/META.yml
jifty/trunk/Makefile.PL
jifty/trunk/lib/Jifty/Web/Session.pm
Log:
* Jifty::Web::Session::ClientSide - Client-side sessions.
Modified: jifty/trunk/META.yml
==============================================================================
--- jifty/trunk/META.yml (original)
+++ jifty/trunk/META.yml Tue Jul 25 15:59:57 2006
@@ -14,6 +14,7 @@
- inc
requires:
App::CLI: 0.03
+ CGI::Cookie::Splitter: 0
CSS::Squish: 0.05
Cache::Cache: 0
Calendar::Simple: 0
@@ -22,6 +23,8 @@
Class::Container: 0
Class::Data::Inheritable: 0
Compress::Zlib: 0
+ Crypt::CBC: 0
+ Crypt::Rijndael: 0
DBD::SQLite: 1.11
Data::Page: 0
Date::Manip: 0
Modified: jifty/trunk/Makefile.PL
==============================================================================
--- jifty/trunk/Makefile.PL (original)
+++ jifty/trunk/Makefile.PL Tue Jul 25 15:59:57 2006
@@ -10,6 +10,9 @@
requires('Class::Accessor::Named');
requires('Class::Container');
requires('Class::Data::Inheritable');
+requires('CGI::Cookie::Splitter');
+requires('Crypt::CBC');
+requires('Crypt::Rijndael');
requires('Compress::Zlib');
requires('CSS::Squish' => 0.05 );
requires('DBD::SQLite' => 1.11 );
Modified: jifty/trunk/lib/Jifty/Web/Session.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Web/Session.pm (original)
+++ jifty/trunk/lib/Jifty/Web/Session.pm Tue Jul 25 15:59:57 2006
@@ -20,7 +20,15 @@
sub new {
my $class = shift;
- return bless {}, $class;
+
+ my $session_class = Jifty->config->framework('Web')->{'SessionClass'};
+ if ($session_class and $class ne $session_class) {
+ Jifty::Util->require( $session_class );
+ return $session_class->new(@_);
+ }
+ else {
+ return bless {}, $class;
+ }
}
=head2 id
@@ -48,9 +56,9 @@
unless ($session_id) {
my %cookies = CGI::Cookie->fetch();
- my $cookiename = $self->cookie_name;
+ my $cookie_name = $self->cookie_name;
$session_id
- = $cookies{$cookiename} ? $cookies{$cookiename}->value() : undef;
+ = $cookies{$cookie_name} ? $cookies{$cookie_name}->value() : undef;
}
my $session = Jifty::Model::Session->new;
@@ -285,14 +293,14 @@
=head2 cookie_name
Returns the current session's cookie_name -- it is the same for all
-users, but various accorting to the port the server is running on.
+users, but varies accorting to the port the server is running on.
=cut
sub cookie_name {
my $self = shift;
- my $cookiename = "JIFTY_SID_" . ( $ENV{'SERVER_PORT'} || 'NOPORT' );
- return ($cookiename);
+ my $cookie_name = "JIFTY_SID_" . ( $ENV{'SERVER_PORT'} || 'NOPORT' );
+ return ($cookie_name);
}
=head2 expires [VALUE]
Added: jifty/trunk/lib/Jifty/Web/Session/ClientSide.pm
==============================================================================
--- (empty file)
+++ jifty/trunk/lib/Jifty/Web/Session/ClientSide.pm Tue Jul 25 15:59:57 2006
@@ -0,0 +1,223 @@
+package Jifty::Web::Session::ClientSide;
+
+=head1 NAME
+
+Jifty::Web::Session - Session handler for client-side sessions
+
+=head1 SYNOPSIS
+
+In your F<etc/config.yml>:
+
+ framework:
+ Web:
+ SessionClass: Jifty::Web::Session::ClientSide
+ SessionSecret: secret_passphrase
+
+=cut
+
+use strict;
+use warnings;
+use base 'Jifty::Web::Session';
+use Jifty::Model::Session();
+use Jifty::YAML ();
+use Compress::Zlib ();
+use Crypt::CBC ();
+use Crypt::Rijndael ();
+use CGI::Cookie::Splitter ();
+
+my $session_key;
+my $splitter = CGI::Cookie::Splitter->new;
+
+=head2 new
+
+Returns a new, empty session handler, subclassing L<Jifty::Web::Session>.
+
+=cut
+
+sub new {
+ my $class = shift;
+ my $session_key = Jifty->config->framework('Web')->{'SessionSecret'}
+ or die "Please set SessionSecret in your framework/Web settings";
+ my $cipher = Crypt::CBC->new(
+ -key => $session_key,
+ -cipher => 'Rijndael',
+ );
+ bless { _cipher => $cipher, _session => undef }, $class;
+}
+
+=head2 _cipher
+
+Accessor to the underlying L<Crypt::CBC> object that encapsulates the
+server-side secret.
+
+=cut
+
+sub _cipher {
+ my $self = shift;
+ $self->{'_cipher'} = shift if (@_);
+ return ( $self->{'_cipher'} );
+}
+
+=head2 id
+
+Returns the session's id if it has been loaded, or C<undef> otherwise.
+
+=cut
+
+sub id {
+ my $self = shift;
+ return $self->loaded ? $self->_session->{session_id} : undef;
+}
+
+=head2 load [ID]
+
+Load up the current session from the given C<ID>, or the appropriate
+cookie (see L<Jifty::Web::Session/cookie_name>) otherwise.
+
+If both of those fail, creates a session in memory.
+
+=cut
+
+sub load {
+ my $self = shift;
+ my $session_id = shift;
+ my %cookies = CGI::Cookie->fetch();
+
+ unless ($session_id) {
+ my $cookie_name = $self->cookie_name;
+ $session_id = $cookies{$cookie_name}
+ ? $cookies{$cookie_name}->value()
+ : Jifty::Model::Session->new_session_id,
+ }
+
+ # XXX - Cookie mangling detection
+ if (exists $cookies{"JIFTY_DAT_$session_id"}) {
+ local $@;
+ eval {
+ $self->_session(
+ Jifty::YAML::Load(
+ Compress::Zlib::uncompress(
+ $self->_cipher->decrypt(
+ $cookies{"JIFTY_DAT_$session_id"}->value
+ )
+ )
+ )
+ );
+ die "Session id mismatch"
+ unless $self->_session->{session_id} eq $session_id;
+ 1;
+ } and return;
+ warn $@ if $@;
+ }
+
+ $self->_session({
+ session_id => $session_id,
+ continuation => {},
+ metadata => {},
+ key => {},
+ });
+}
+
+=head2 get KEY [TYPE]
+
+See L<Jifty::Web::Session/get>.
+
+=cut
+
+sub get {
+ my $self = shift;
+ my $key = shift;
+ my $key_type = shift || "key";
+
+ return undef unless $self->loaded;
+ return $self->_session->{$key_type}{$key};
+}
+
+=head2 set KEY => VALUE, [TYPE]
+
+See L<Jifty::Web::Session/set>.
+
+=cut
+
+sub set {
+ my $self = shift;
+ my $key = shift;
+ my $value = shift;
+ my $key_type = shift || "key";
+
+ return undef unless $self->loaded;
+ $self->_session->{$key_type}{$key} = $value;
+
+ # XXX - delay until the very last moment?
+ $self->flush;
+}
+
+=head2 remove KEY, [TYPE]
+
+See L<Jifty::Web::Session/remove>.
+
+=cut
+
+sub remove {
+ my $self = shift;
+ my $key = shift;
+ my $key_type = shift || "key";
+
+ return undef unless $self->loaded;
+ delete $self->_session->{$key_type}{$key};
+}
+
+=head2 continuations
+
+See L<Jifty::Web::Session/continuations>.
+
+=cut
+
+sub continuations {
+ my $self = shift;
+ return () unless $self->loaded;
+ return %{ $self->_session->{continuation} };
+}
+
+=head2 unload
+
+See L<Jifty::Web::Session/unload>.
+
+=cut
+
+sub unload {
+ my $self = shift;
+ $self->flush;
+ $self->_session(undef);
+}
+
+=head2 flush
+
+Outputs the client-side session as one or more cookies.
+
+=cut
+
+sub flush {
+ my $self = shift;
+ my $session_id = $self->id or return;
+
+ my $data_cookie = CGI::Cookie->new(
+ -name => "JIFTY_DAT_$session_id",
+ -expires => $self->expires,
+ -value => $self->_cipher->encrypt(
+ Compress::Zlib::compress(
+ Jifty::YAML::Dump(
+ $self->_session
+ )
+ )
+ )
+ );
+
+ foreach my $cookie ($splitter->split( $data_cookie )) {
+ Jifty->web->response->add_header(
+ 'Set-Cookie' => $cookie->as_string
+ );
+ }
+}
+
+1;
More information about the Jifty-commit
mailing list