#!/usr/bin/perl # $Id: guestbook.cgi,v 1.5 2005-10-10 15:12:47 dave Exp $ # Dave Holland # released under the GPL # vi:sw=4:ts=4:ai:cindent use Net::OpenID::Consumer; use CGI qw(:standard); use CGI::Pretty; use CGI::Cookie; use Digest::SHA1 qw(sha1 sha1_hex); use HTML::Entities; use DB_File; $guestbookfile="/home/dave/openid/guestbook.txt"; $iddb="/home/dave/openid/iddb"; $|=1; $cgi = CGI->new(); $con = Net::OpenID::Consumer->new( ua => LWP::UserAgent->new, # FIXME - use LWPx::ParanoidAgent cache => undef, # or File::Cache->new, args => $cgi, consumer_secret => \&mysecret, required_root => "http://www.biff.org.uk/" ); # FIXME - http/s $this_script = "http://".$ENV{'HTTP_HOST'}.$ENV{'SCRIPT_NAME'}; if($cgi->cookie('biff-openid')) { #print header, "found cookie: ", $cgi->cookie('biff-openid'); if(param()) { if(param('logout')) { &delid($cgi->cookie('biff-openid')); print redirect( -url=> $this_script, -cookie => new CGI::Cookie(-name => 'biff-openid', -value => "", -expires => '-1d'), ); exit(0); } elsif(param('entry')) { &addentry; } } print header, start_html(-title=>"OpenID guestbook", -onLoad=>"document.fred.id.focus();"), h1("OpenID guestbook"); &gform; &listbook; exit(0); } # no cookie? try to auth with openid if(param()) { if(param('ret')) { if($setup_url = $con->user_setup_url) { &log("need to redirect to",$setup_url); print $cgi->redirect($setup_url); } elsif ($con->user_cancel) { &log("user cancel"); print redirect(-url=>$this_script); } elsif ($vident = $con->verified_identity) { $verified_url = $vident->url; &log("verified as $verified_url"); $r=&saveid($verified_url); print redirect( -url => $this_script, -cookie => new CGI::Cookie(-name => 'biff-openid', -value => $r), ); } else { &log("error validating identity:", $con->err); print header, "error validating identity: ", $con->err, p; &print_params; } exit(0); } elsif(param('id')) { #print "presented id: ",param('id'),"

\n"; $claimed = $con->claimed_identity(param('id')); if(!defined($claimed)) { &log("claim for",param('id'),"failed:", $con->err); print header, "claim for ",param('id')," failed: ", $con->err, p; &print_params; exit(0); } #print "claimed id: ",$claimed->claimed_url,"

\n"; $check_url = $claimed->check_url( return_to => $this_script."?ret=true", trust_root => "http://www.biff.org.uk/"); &log("redirecting to", $check_url); print $cgi->redirect($check_url); exit(0); } else { &log("param but no ret or id"); print header, "hmm, param but no ret or id"; exit(0); } } else { print header, start_html(-title=>"OpenID guestbook", -onLoad=>"document.fred.id.focus();"), h1("OpenID guestbook"), start_form(-name=>"fred"), "enter OpenID: ", textfield(-name=>'id', -size=>35, -style=>'background: url(http://stat.livejournal.com/img/openid-inputicon.gif) no-repeat; background-color: #fff; background-position: 0 50%; padding-left: 18px;'), # FIXME use a local copy of this image " ", submit(-name=>"verify"), p, "e.g. www.biff.org.uk/dave or username.livejournal.com", end_form; &listbook; exit(0); } exit(0); sub mysecret { my $t=shift; if(! $t) { $t=time(); &log("secret called with no param: using",$t); } $t -= $t % 3600; # one hour granularity #return($t); $s=sha1_hex("foo".($t - $t % 3600)); # FIXME change "foo" if you copy this script &log("secret:",$t,$s); return("$s"); } sub log { open(L,">>/home/dave/openid/openid.log") or return; print L scalar(localtime)." ".$ENV{'REMOTE_ADDR'}." ".$$. " ".join(" ",@_)."\n"; close(L); } sub print_params { @names=param; foreach $n (@names) { print $n, " = ", param($n), br; } } # print guestbook entry form sub gform { my $id=&lookupid($cgi->cookie('biff-openid')); if($id eq "") { print "You need to ", a({href=>$this_script},"log in"), "before you can leave a comment."; return; } print start_form(-name=>"fred"), "Hello ", a({href=>$id},$id), ", enter your comment here:", p, textarea(-name=>"entry", -default=>"", -override=>1, -rows=>3, -columns=>50), p, submit(-name=>"add entry"), " ", submit(-name=>"logout"), end_form, p; } # dump guestbook contents sub listbook { print hr, p; if(! -s $guestbookfile) { print i("guestbook is empty - add an entry!"); return; } open(B,$guestbookfile) or return; while() { ($id,$time,$rest) = split(' ',$_,3); print scalar(localtime($time)), " ", a({href=>$id},$id), " : ", encode_entities($rest), br; } close(B); } # add an entry sub addentry { return if (param('entry') =~ m/^\s*$/); open(B,">>".$guestbookfile) or return; my $e=param('entry'); $e=~s/\s/ /g; # no sneaky embedded newlines print B &lookupid($cgi->cookie('biff-openid')), " ", time, " ", $e, "\n"; close(B); } # given a handle, look up the url sub lookupid { my $c=shift; return "" if ($c eq ""); $db=tie(%db,'DB_File',$iddb,O_CREAT|O_RDWR,0644) or die "dbcreat: $!\n"; my $v=$db{$c}; undef $db; untie %db; return($v); } # given a url, save it and return a handle sub saveid { my $vurl=shift; $db=tie(%db,'DB_File',$iddb,O_CREAT|O_RDWR,0644) or die "dbcreat: $!\n"; $db{$$}=$vurl; undef $db; untie %db; return($$); } # given a handle, delete it from the db sub delid { my $id=shift; $db=tie(%db,'DB_File',$iddb,O_CREAT|O_RDWR,0644) or die "dbcreat: $!\n"; $db{$id}=""; undef $db; untie %db; return($$); }