1 package VJournal::Session;
9 use vars qw($AUTOLOAD);
10 use constant COOKIE_NAME=>'VJ_SESSION';
11 use constant CONFIG_NAME=>'.vjournalrc';
18 VJournal::Session - handle authorized use session
23 my $s = VJournal::Session->new;
27 B<VJournal::Session> manages session. Sesssion objects incoroprates
28 B<CGI.pm> context, and any methods of CGI.pm can be called as session
35 $session = new VJournal::Session();
36 $session = new VJournal::Session($cgi);
38 Creates new B<session> object based on the CGI request. If no CGI
39 object is expilcitely provided, creates one using default constructor.
41 If there is no session cookie in the CGI context, or cookie is expired,
42 or cookie is bound to IP address, other than current B<remote_addr()>,
51 %attrs=(-cgi=>new CGI);
52 } elsif (scalar(@_)%2==0) {
54 } elsif (scalar(@_) == 1) {
57 croak "Invalid call to VJournal::Session::new"
59 if (exists $attrs{-cgi} && $attrs{-cgi}->can("cookie")) {
61 my $sess_id = $cgi->cookie(COOKIE_NAME);
62 return undef unless $sess_id;
64 if (!exists($config{-sessionbase})) {
65 croak "No VJournal config read";
68 dbmopen %userbase,$config{-sessionbase},0644;
70 return undef if (!exists($userbase{$sess_id}));
71 my ($name,$avatar,$email,$avwidth,$avheight,$ip,$expire) =
72 split(/:/,$userbase{$sess_id});
73 if ($ip && $ip ne $attrs{-cgi}->remote_addr()) {
76 my $me={-id=>$sess_id,-name=>$name,-cgi=>$cgi};
78 $me->{-avatar}=$avatar;
79 $me->{-avwidth}=$avwidth;
80 $me->{-avheight}=$avheight;
88 delete $userbase{$sess_id};
90 } elsif ($expire < $now - $config{-gracetime}) {
91 $expire+=$config{-sessiontime};
92 $userbase{$sess_id}=join(":",$name,$avatar,$email,$avwidth,$avheight,$ip,$expire);
94 [$cgi->cookie(-name=>COOKIE_NAME,-value=>$sess_id,-expires=>
97 return bless $pkg,$me;
103 Creates new session for given user. It is assumet that user have been
104 properly authenticated by caller. (i.e. using OpenID).
106 $session=VJournal::Session->create(-user=>'user',-cgi=>$cgi,-email=>$mailaddress,
111 If B<-bind_to_ip> is specified, session would be bound to IP address.
112 Avatar uri and email address might be provided by the authentication
115 If they are not obtained for free, caller shouldn't attempt to provide
116 them to create. Better to check if avatar and email are defined after
117 session creation. May be they are already cached.
123 if (scalar(@_)%2!=0) {
124 croak("Invalid call to ".$pkg."->create");
127 croack("User name is required by ".$pkg."->creae");
128 $params{-cgi}=CGI->new() if(!$params{-cgi});
129 load_config($params{-cgi});
137 $s->avatar("http://www.some.site/userpic/user.gif");
139 In the scalar context returns img tag for user avatar.
140 In the vector context returns list which looks like
142 -src=>http://some.site/some.pic, -width=>nnn,-height=>nnn,-alt=>username
144 If URL is supplied, attempts to cache image in the local userpic area
145 so subsequent calls to the avatar would return local copy.
153 require VJournal::Avatar;
154 my %a = VJournal::Avatar::cache($_[0]);
155 while (my($key,$val)=each %a) {
158 $self->_update_user();
159 } elsif (exists($self->{-avatar})) {
160 my @a=(-src=>$self->{-avatar},-width=>$self->{-avwidth},-height=>$self->{-avheight},-alt=>$self->{-name});
164 return $self->{-cgi}->img(@a);
171 my $addr=$s->email();
180 $self->{-email} = shift;
181 if (!exists $self->{-avatar}) {
182 require VJournal::Avatar;
183 VJournal::Avatar::by_email($self->{-email});
185 $self->_update_user();
187 return $self->{-email};
195 returns true, if current user is owner of the blog
201 return $self->{-name} eq $config{-owner};
208 Updates intformation about user in the user and session database.
209 Internal function, called from B<create>, B<avatar> and B<email>.
215 Overrideds CGI.pm header routine and adds to the header Set-Cookie
216 headers for cookies created by B<new>, B<create> or added by B<set_cookie>
222 push @_,-cookie=>$self->{-cookie} if exists($self->{-cookie}) ;
223 return $self->{-cgi}->header(@_);
230 walks up the path_translated() and searches for the B<.vjournalrc> config.
231 dies if config not found.
236 my $path=$_[0]->path_translated();
237 my @dirs = (File::Spec->splitdir($path));
240 my $d=File::Spec->catdir(@dirs,CONFIG_NAME);
246 eval "%config = {$d}";
252 die ("Cannot find config file inside $path") unless $found;
253 my @reqkeys=qw(-owner -statedir -templatedir);
254 foreach my $key (@reqkeys) {
255 die "Required key $key missing from config"
256 unless exists $config{$key};
259 $config{-sessionbase}||=$config{-statedir}."/sessions.db";
260 $config{-userbase}||=$config{-statedir}."/user.db";
261 $config{-sessiontime}||=86400*30;
262 $config{-gracetime}||=86400;
267 Delegates all called methods which are not implemented to the CGI.pm
275 my $func = $AUTOLOAD;;
276 croak("Invalid method $AUTOLOAD") unless CGI->can($func);
277 return $self->{-cgi}->$func(@_);