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 $me,$pkg;
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") unless $params{-user};
128 $params{-cgi}=CGI->new() if(!$params{-cgi});
129 load_config($params{-cgi});
130 my $user=$params{-user};
133 dbmopen %users,$config{-userbase},0644;
134 my $session={-cgi=>$params{-cgi},-name=>$params{-user}};
135 if (!exists($users{$user})) {
137 require VJournal::Avatar;
139 if (exists $params{-avatar}) {
140 @avatar = VJournal::Avatar::cache($params{-avatar});
142 @avatar = VJournal::Avatar::by_openid($user);
144 if (!@avatar && exists $params{-email}) {
145 @avatar = VJournal::Avatar::by_email($params{-email});
148 $users{$user}=join(":",$params{-email},$a{-src},$a{-width},$a{-height});
150 my ($email,$avatarsrc,$avatarwidth,$avatarheight)=split(":",$users{$user});
151 $session->{-email} = $email if $email;
153 $session->{-avatar} = $avatarsrc;
154 $session->{-avwidth} = $avatarwidth;
155 $session->{-avheight} = $avatarheight;
157 my $expire = time()+$config{-sessiontime};
160 $sessioninfo=join(":",$user,$avatarsrc,$email,$avatarwidth,$avatarheight,
161 ($params{-bind_to_ip}?$session->{-cgi}->remote_addr():""),$expire);
162 $session->{-id} = Digest::MD5::md5_base64($sessioninfo);
163 $sessions{$session->{-id}} = $sessioninfo;
166 [$session->cookie(-name=>COOKIE_NAME,-value=>$session->{-id},-expires=>
173 $s->set_cookie($s->cookie(-name=>name,-value=>value));
175 Stores new cookie to be send to client inside the session object.
176 They would be output when $s->header would be printed.
182 $self->{-cookie}=[] if !exists $self->{-cookie};
183 push @{$self->{-cookie}},@_;
190 $s->avatar("http://www.some.site/userpic/user.gif");
192 In the scalar context returns img tag for user avatar.
193 In the vector context returns list which looks like
195 -src=>http://some.site/some.pic, -width=>nnn,-height=>nnn,-alt=>username
197 If URL is supplied, attempts to cache image in the local userpic area
198 so subsequent calls to the avatar would return local copy.
206 require VJournal::Avatar;
207 my %a = VJournal::Avatar::cache($_[0]);
208 while (my($key,$val)=each %a) {
211 $self->_update_user();
212 } elsif (exists($self->{-avatar})) {
213 my @a=(-src=>$self->{-avatar},-width=>$self->{-avwidth},-height=>$self->{-avheight},-alt=>$self->{-name});
217 return $self->{-cgi}->img(@a);
224 my $addr=$s->email();
233 $self->{-email} = shift;
234 if (!exists $self->{-avatar}) {
235 require VJournal::Avatar;
236 VJournal::Avatar::by_email($self->{-email});
238 $self->_update_user();
240 return $self->{-email};
248 returns true, if current user is owner of the blog
254 return $self->{-name} eq $config{-owner};
261 Updates intformation about user in the user and session database.
262 Internal function, called from B<create>, B<avatar> and B<email>.
268 Overrideds CGI.pm header routine and adds to the header Set-Cookie
269 headers for cookies created by B<new>, B<create> or added by B<set_cookie>
275 push @_,-cookie=>$self->{-cookie} if exists($self->{-cookie}) ;
276 return $self->{-cgi}->header(@_);
283 walks up the path_translated() and searches for the B<.vjournalrc> config.
284 dies if config not found.
289 my $path=$_[0]->path_translated();
290 my @dirs = (File::Spec->splitdir($path));
293 my $d=File::Spec->catdir(@dirs,CONFIG_NAME);
299 eval "%config = {$d}";
305 die ("Cannot find config file inside $path") unless $found;
306 my @reqkeys=qw(-owner -statedir -templatedir);
307 foreach my $key (@reqkeys) {
308 die "Required key $key missing from config"
309 unless exists $config{$key};
312 $config{-sessionbase}||=$config{-statedir}."/sessions.db";
313 $config{-userbase}||=$config{-statedir}."/user.db";
314 $config{-sessiontime}||=86400*30;
315 $config{-gracetime}||=86400;
320 Delegates all called methods which are not implemented to the CGI.pm
328 my $func = $AUTOLOAD;;
329 croak("Invalid method $AUTOLOAD") unless CGI->can($func);
330 return $self->{-cgi}->$func(@_);