Last month, I gave a rough introduction of Apache::ASP, and why you might want to use it to build your web site. Now I get to show you Apache::ASP in action.
This site will require a user to login with a chosen user name for security, and view, add, and delete their internet bookmarks. The deletion will leave the deleted bookmark data in the form to allow easy modification and recreation of that bookmark.
The user will also be able to logout, and the system will auto-logout their account automatically after 15 minutes, so that if it is a public terminal, another user using the same browser later will not be able modify the first user's bookmarks.
Also, because our web application has more than one page, we will make use of the same headers and footers for each page, using the includes <!--#include file=src.inc--> functionality to modularize the html.
You might also design the objects, methods, and functions that will be used for the site, but this site is so simple, that we are going to jump into implementation.
# .htaccess |
DirectoryIndex index.asp <Files ~ \.asp$> SetHandler perl-script PerlHandler Apache::ASP PerlSetVar Global . PerlSetVar GlobalPackage My::Bookmarks PerlSetVar StateDir /tmp/asp_apps_bookmarks PerlSetVar Debug 2 PerlSetVar SessionTimeout 15 PerlSetVar StatScripts 1 PerlSetVar AllowApplicationState 1 PerlSetVar AllowSessionState 1 </Files> |
# dummy.asp |
INTRO <%=$Session%> |
If the index.asp works on your server, and just prints INTRO Apache::ASP::Session=HASH(0x??????), then we know Apache::ASP is working and $Sessions are enabled.
Notice that each script can process its own Logout request, which was a decision made after the design because it seemed good to make the first script, index.asp, $Session aware.
# global.asa |
use File::Basename; use DBI; use DBD::CSV; use vars qw( $DarkColor $Name %Titles $FontBase $Db $Title $Basename $Form $Query ); $DarkColor = '#0000aa'; $Name = "MyBookmarks"; %Titles = ( 'index.asp' => 'Introduction', 'bookmarks.asp' => 'Viewer' ); $FontBase = 'face=verdana,arial'; $Db = DBI->connect("DBI:CSV:f_dir=".Apache->dir_config('StateDir'), '', '', { RaiseError => 1 }) or die "Cannot connect: " . $DBI::errstr; # setup bookmark database if first time unless(eval { $Db->do("select bookmark_id,username,title,url from bookmarks") }) { eval { $Db->do("drop table bookmarks"); }; $Db->do(<<CREATE) || die("can't create table $DBI::errstr"); create table bookmarks ( bookmark_id varchar(15), username varchar(30), title varchar(60), url varchar(120) ) CREATE ; } $Db->do("select * from bookmarks") || die("can't do select against bookmarks: $DBI::errstr"); sub Script_OnStart { $Basename = basename($0); $Title = $Name.' / '.$Titles{$Basename}; $Response->Include('header.inc'); $Form = $Request->Form(); $Query = $Request->QueryString(); $Response->Expires(0); # a user may logout from any script, destroy session, and go # to login / intro page if($Form->{logout}) { $Session->Abandon(); $Response->Redirect("index.asp?abandon=". ++$Application->{abandon}); } } sub Script_OnEnd { $Response->Include('footer.inc'); } sub Application_OnStart { # use max_bookmark_id as a pseudo sequence $Application->Lock(); my $sth = $Db->prepare_cached ("select bookmark_id from bookmarks order by bookmark_id desc"); $sth->execute(); $Application->{max_bookmark_id} = $sth->fetchrow_array(); $Application->UnLock(); } |
# header.inc |
<html> <head><title><%=$Title%></title></head> <body bgcolor=white link=purple alink=yellow vlink=gray> <form src=<%=$Basename%> method=POST> <table border=0 width=100% cellpadding=5 cellspacing=0> <tr bgcolor=<%= $DarkColor %>> <td> <b><font <%=$FontBase%> size=+1 color=yellow> <%=$Title%> <% if($Session->{user}) { %> for <%= $Session->{user} %> <% } %> </font></b> </td> <td align=right> <font <%=$FontBase%>> <% if($Session->{'user'}) { %> <input type=submit name=logout value=Logout> <% } else { %> <% } %> </font> </td> </tr> </form> </table> <table border=0 cellpadding=5 width=100% ><tr><td valign=top> <font <%=$FontBase%> size=+0> |
# footer.inc |
</font> </table> <table border=0 width=100% cellpadding=5> <tr> <td bgcolor=yellow align=center> <font <%=$FontBase%> size=-1 color=<%= $DarkColor %>> <b> My-NotExists-Bookmarks Cool Technologies Etc., ???, © <%= (localtime())[5] + 1900 %> </b> </font> </td> </tr> </table> </body> </html> |
# index.asp |
<% # process user login my $error; my $user = $Form->{'user'}; if(defined $user) { $user =~ /^\w+$/ or $error = "Your username must made of only letter and numbers"; length($user) > 3 or $error = "Your username much be at least 4 character long"; unless($error) { $Session->{user} = $user; $Response->Redirect('bookmarks.asp'); } } $user ||= $Session->{user}; %> Hello, and welcome to the MyBookmarks Apache::ASP demo application. To begin your bookmark experience, please login now: <center> <% if($error) { %> <p><b><font color=red size=-1>* <%=$error%></font></b> <% } %> <form src=<%=$Basename%> method=POST> <input type=text name=user value="<%=$Server->HTMLEncode($user)%>"> <input type=submit value=Login> </form> </center> This demo makes use of the Apache::ASP objects, especially <tt>$Session</tt> and <tt>$Response</tt>, modularizes html via SSI file includes, and uses the <tt>Script_OnStart</tt> and <tt>Script_OnEnd</tt> event hooks to simplify common tasks done for each script in this web application. |
# bookmarks.asp |
<% # only a logged in user may view the bookmarks $Session->{'user'} || $Response->Redirect('index.asp'); my $error; if($Form->{submit} =~ /create/i) { unless($Form->{new_url}) { $error = "The Url must be ". "filled in to create a new bookmark"; goto ERROR; } my $sth = $Db->prepare_cached( "select url from bookmarks where username=? and url=?" ); $sth->execute($Session->{'user'}, $Form->{new_url}); if($sth->fetchrow_array) { $error = "You already have $Form->{new_url} ". "for a bookmark"; goto ERROR; } else { $sth = $Db->prepare_cached(<<SQL); insert into bookmarks (bookmark_id, username, url, title) values (?,?,?,?) SQL ; $Application->Lock(); $sth->execute( ++$Application->{max_bookmark_id}, $Session->{'user'}, $Form->{new_url}, $Form->{new_title} ); $Application->UnLock(); } } if($Query->{delete}) { my $sth = $Db->prepare_cached(<<SQL); select * from bookmarks where bookmark_id = ? and username = ? SQL ; $sth->execute($Query->{delete}, $Session->{user}); if(my $data = $sth->fetchrow_hashref) { my $sth = $Db->prepare_cached(<<SQL); delete from bookmarks where bookmark_id = ? and username = ? SQL ; $sth->execute($Query->{delete}, $Session->{user}); $Form->{new_url} = $data->{'url'}; $Form->{new_title} = $data->{'title'}; } } # get all the bookmarks ERROR: my $sth = $Db->prepare_cached( "select * from bookmarks where username=? ". "order by bookmark_id" ); $sth->execute($Session->{'user'}); my @bookmarks; while(my $bookmark = $sth->fetchrow_hashref()) { push(@bookmarks, $bookmark); } %> <% if(@bookmarks) { %> Welcome to your bookmarks! <% } else { %> You don't have any bookmarks. Please feel free to add some using the below form. <% } %> <center> <% if($error) { %> <p><b><font color=red size=-1>* <%=$error%></font></b> <% } %> <form src=<%=$Basename%> method=POST> <table border=0> <% for ('new_url', 'new_title') { my $name = $_; my $title = join(' ', map { ucfirst $_ } split(/_/, $name)); %> <tr> <td><b><%=$title%>:</b></td> <td><input type=text name=<%=$name%> value="<%=$Form->{$name}%>" size=40 maxlength=120> </td> </tr> <% } %> <tr> <td> </td> <td> <font <%=$FontBase%>> <input type=submit name=submit value="Create Bookmark"></td></tr> </font> </td> </form> </table> <% if(@bookmarks) { my $half_index = int((@bookmarks+1)/2); %> <p> <table border=0 width=80% bgcolor=<%= $DarkColor %> cellspacing=0> <tr><td align=center> <table border=0 width=100% cellspacing=1 cellpadding=3> <tr bgcolor=<%= $DarkColor %>><td align=center colspan=4> <font color=yellow><b>Bookmarks</b></font> </td></tr> <% for(my $i=0; $i<$half_index; $i++) { %> <tr> <% for($i, $i+$half_index) { my $data = ($_ < @bookmarks) ? $bookmarks[$_] : undef; $data->{title} ||= $data->{'url'}; my $text = $data->{bookmark_id} ? "<a href=$data->{'url'} >$data->{'title'}</a>" : " "; %> <td bgcolor=#c0c0c0 width=30 align=center> <% if($data->{bookmark_id}) { %> <font size=-1><tt> <a href=<%= "$Basename?delete=$data->{bookmark_id}" %>>[DEL]</a> </tt></font> <% } else { %> <% } %> </td> <td bgcolor=white><%= $text || ' '%></td> <% } %> </tr> <% } %> </table> </td></tr></table> <br> <% } %> </center> |