Title: Implementing web user interfaces with Perl
1Implementing web user interfaces with Perl
- Rachel Coleman
- MISD-University Card Service
- University of Cambridge
- TechLink Seminar, 6 March 2002
2Put it on the web!
- What you want to do
- What?
- Why?
- For whom?
- Security implications
- How to do it
- tools for CGI, DBI, HTML, application building
- planning and doing
3What do you want to provide?
- View only (catalogue) ?
- Update access too (application)?
4Why do you want it on the web?
- Advantages
- web browsers widely available
- available to more people easily
- update in one place
- Disadvantages
- available to more people easily - security
- limited to HTML for display
5Why web UI for card service?
- Before
- MS Access front-end
- each PC requires Access, OO4O
- PCs must be within UAS network
- Users forgetting to close app can delay code
updates
6Why web UI for card office?
- After
- Web browser already installed on all machines
- Users cannot delay updates to code on server
- Potential to allow access outside UAS
7Who will be using it?
- Card office
- office staff (now), card reps (future)
- Other examples
- existing/potential students
- researchers here/elsewhere
- everyone!
8What will your users need to do?
- Search
- Display (text only? images?)
- Update? (Catalogue or application)
- Different user groups - different privileges
- e.g. card office reps will have read-only access
9Security - users
- Do you need to restrict access by user/user
group? - How will you authorise/authenticate your users?
(see http//www.eng.cam.ac.uk/mjg17/webauth/
for more on this)
10Security - network
- How confidential is your data?
- Should you use SSL?
- How vulnerable is your web server to attack? And
the database server? - What damage could be caused by a successful
break-in?
11Before you start
- What are you trying to do?
- Why are you trying to do it?
- Who will be using it?
- What will they need to do?
- What security holes are you opening up?
- Do you still want to do it?
12How to do it
- Perl is one option (see also Python, PHP, Java
servlets, ASP ) - Resources
- Learning Perl, Schwartz/Christiansen
- Programming Perl, Wall/Christiansen/Schwartz
- www.perl.com
- learn.perl.org
- comp.lang.perl.misc
13Modules and CPAN
- Module
- self-contained set of reusable code
- defined interface
- included in a program by use Module
- CPAN
- Comprehensive Perl Archive Network
- http//www.cpan.org
- dont reinvent the wheel
14Useful modules
- CGI.pm
- The Perl DBI
- HTMLTemplate
- CGIApplication
15CGI.pm
- Perl module for handling CGI tasks
- Widely used standard way for Perl CGI
- Simple to use
- Standard or object-oriented interface
- Online documentation at http//stein.cshl.org/WWW/
software/CGI/
16CGI.pm example - generating HTML
!/usr/bin/perl -w use strict use CGI my q
new CGI print q-gtheader( "text/html" ),
q-gtstart_html( -title gt "Great Rings of Power",
-bgcolor gt "ffffcc" ), q-gtcenter(
q-gth1( "Ring allocation" ), q-gtp(
"The table below illustrates the allocation of
the Great Rings of power. ),
q-gttable( border gt 1, q-gtTr(
align gt "center",
q-gtth( 'Elves', 'Dwarf Lords', 'Mortal Men'
), q-gttd( '3','7','9')
) ) ), q-gtend_html
17CGI.pm example - generating HTML
18CGI.pm example - generating HTML
lt?xml version"1.0" encoding"utf-8"?gt lt!DOCTYPE
html PUBLIC "-//W3C//DTD XHTML Basic
1.0//EN" "http//www.w3.org/TR/xhtml-basic/xhtml-
basic10.dtd"gt lthtml xmlns"http//www.w3.org/1999/
xhtml" lang"en-US"gtltheadgtlttitlegtGreat Rings of
Powerlt/titlegt lt/headgtltbody bgcolor"ffffcc"gtltcent
ergtlth1gtRing allocationlt/h1gt ltpgtThe table below
illustrates the allocation of the Great Rings of
power.lt/pgt lttable border"1"gtlttr
align"center"gtltthgtElveslt/thgt ltthgtDwarf
Lordslt/thgt ltthgtMortal Menlt/thgtlt/trgt lttr
align"center"gtlttdgt3lt/tdgt lttdgt7lt/tdgt
lttdgt9lt/tdgtlt/trgtlt/tablegtlt/centergtlt/bodygtlt/htmlgt
Source produced is messy - but thats not what
you work with
19CGI.pm example - accessing input
!/usr/bin/perl -w use strict use CGI my q
new CGI my forename q-gtparam('forename') my
surname q-gtparam('surname') print
q-gtheader( "text/html" ), q-gtstart_html(
-title gt "People", -bgcolor gt "ffffcc" ),
q-gtcenter( q-gtp( "The following values
were received" ), q-gtp( "Surname
surname" ), q-gtp( "Forename forename"
) ), q-gtend_html
Parameters supplied, e.g. in query
string https//10.0.12.3/rachel/cgi/sample2.cgi?
surnameBagginsforenameBilbo
20CGI.pm example - accessing input
21CGI.pm example - Taint mode
- All data from user is tainted
- Tainted data may not be used to affect anything
external e.g. passed in database query, passed to
shell, any file changes - To use data, you must untaint it using regular
expression
!/usr/bin/perl -wT use strict use CGI my q
new CGI my ( surname ) q-gtparam('surname')
/(a-zA-Z)/ print q-gtheader(
"text/html" ), q-gtstart_html( -title gt
"People", -bgcolor gt "ffffcc" ),
q-gtcenter( q-gtp( "The following values
were received" ), q-gtp( "Surname
surname" ), ), q-gtend_html
22CGI.pm example - Taint mode
my ( surname ) q-gtparam('surname')
/(a-zA-Z)/
23CGI.pm example - Taint mode
my ( surname ) q-gtparam('surname')
/(a-zA-Z)/
24Why use Taint mode?
- Never trust the user
- Never trust the browser to restrict access to
data - Use taint
- When untainting decide what to allow, and allow
nothing else
25The Perl DBI
- Simple high-level interface to any database
Diagram reproduced courtesy of Alligator Descartes
26DBI
- Uses DBD to connect to specific database (e.g.
Oracle, Sybase, mySQL, many more...) - Based on issuing SQL commands and fetching data
back - Documentation at http//dbi.perl.org and CPAN
- Programming the Perl DBI, Descartes/Bunce
27DBI example - simple fetch
!/usr/bin/perl -w use strict use DBI my
attr ( PrintError gt 0, RaiseError gt
1, AutoCommit gt 0 ) my dbh
DBI-gtconnect( dbiOraclehostnnn.nnn.nnn.nn
nsidCARD" USER", PASSWORD", \attr )
or die ( DBIerrstr, "\n") my sth
dbh-gtprepare( " SELECT surname, forenames
FROM vw_cardholders WHERE surname
'Coleman' ORDER BY forenames "
) sth-gtexecute sth-gtdump_results dbh-gtdisc
onnect
rachel_at_apollo talk perl dbi1.pl 'Coleman',
'Andrew Thomas Guy' 'Coleman', 'Anthony
Patrick' 'Coleman', 'Eliza' 'Coleman', 'Gillian
Mary' 'Coleman', 'Heather Margaret' 'Coleman',
'Jamie' 'Coleman', 'Jonathan David' 'Coleman',
'Martin Richard' 'Coleman', 'Nicholas' 'Coleman',
'Pamela Ashleigh' 'Coleman', 'Rachel
Mary' 'Coleman', 'Sam Joseph' 'Coleman', 'Thomas
McKinney' 'Coleman', 'Thomas William' 'Coleman',
'Toby John' 'Coleman', 'Toby William' 16
rows rachel_at_apollo talk
28DBI example - line-at-time
my sth dbh-gtprepare( " SELECT surname,
forenames FROM vw_cardholders WHERE surname
'Coleman' ORDER BY forenames " ) my (
sur, fore ) sth-gtexecute while ( sur,
fore ) sth-gtfetchrow_array ) print
"forenames surname\n" dbh-gtdisconnect
rachel_at_apollo talk perl dbi2.pl Andrew Thomas
Guy Coleman Anthony Patrick Coleman Eliza
Coleman Gillian Mary Coleman Heather Margaret
Coleman Jamie Coleman Jonathan David
Coleman Martin Richard Coleman Nicholas
Coleman Pamela Ashleigh Coleman Rachel Mary
Coleman Sam Joseph Coleman Thomas McKinney
Coleman Thomas William Coleman Toby John
Coleman Toby William Coleman rachel_at_apollo
talk
29DBI example - atomic fetch
my _at_results dbh-gtselectrow_array( " SELECT
FROM vw_cardholders WHERE surname'Coleman' AND
forenames like 'Rachel' " ) foreach my
field ( _at_results ) field "" unless
field print "field\n" dbh-gtdisconnect
rachel_at_apollo talk perl dbi3.pl rc0153f Rachel
Mary Coleman 28-JUN-77 91540 nl219 153 48866
rachel_at_apollo talk
30Binding columns and bind values
my sth_hold dbh-gtprepare( " SELECT
cam_uid FROM vw_cardholders WHERE surname
Bolton' ORDER BY cam_uid " ) my sth_card
dbh-gtprepare( " SELECT issue_number,
photo_id, tdsi_number, expiry_date FROM
vw_cards WHERE cam_uid ? ORDER BY issue_number
" ) my uid print "Card ID\tIssue\tPhoto?\t
TDSI\tExpires?\n" sth_hold-gtexecute sth_hold-
gtbind_col( 1, \uid ) while ( sth_hold-gtfetch
) my ( iss, phot, tdsi, exp )
sth_card-gtbind_param( 1, uid )
sth_card-gtexecute sth_card-gtbind_columns(
\iss, \phot, \tdsi, \exp ) while (
sth_card-gtfetch ) my is_photo phot
(phot gt 0) ? "Y" "N" my
is_printed tdsi ? "Y" "N" print
"uid\tiss\tis_photo\tis_printed\texp\n"
31Binding columns and bind values
rachel_at_apollo talk perl dbi4.pl Card ID Issue
Photo? TDSI Expires? ab0290b 1 Y
Y 01-AUG-04 cb0083m 1 Y Y
28-JUL-04 cb0162r 1 Y Y
04-JAN-04 cb0166c 1 Y Y
18-SEP-01 cb0247a 1 Y Y
01-JAN-04 db0057w 1 N N
28-FEB-06 eb0048k 1 N N
31-JUL-02 hb0035b 1 Y Y
01-OCT-01 ib0015y 1 Y Y
30-JUN-03 lb0095q 1 Y Y
18-SEP-01 mb0096f 1 Y Y
30-JUN-03 mb0261u 1 N N
28-FEB-06 mb0356b 1 Y Y
12-DEC-05 mb0356b 2 Y Y
10-JAN-06 pb0056q 1 N N
30-JUN-03 rb0131t 1 Y Y
18-JUN-01 rb0131t 2 Y Y
20-SEP-05 rb0191h 1 Y Y
01-AUG-04 rb0191h 2 Y Y
30-SEP-04 sb0354t 1 Y Y
30-SEP-04 tb0130f 1 Y Y
02-OCT-05 rachel_at_apollo talk
32HTMLTemplate
- Adds the following to HTML
- variables
- loops
- if-then-else
- Allows separation of page design and code design
- Allows component reuse
33(No Transcript)
34(No Transcript)
35HTMLTemplate example
outer.tmpl
lt!doctype html public "-//w3c//dtd html 4.01
Frameset//en" "http//www.w3.org/TR/ht
ml4/frameset.dtd"gt ltheadgt lttitlegtUniversity
Card Interfacelt/titlegt lt/headgt ltbody
bgcolor"99ccff" text"000000" link"3300cc"
alink"ff0000" vlink"990066"gt ltcentergt lth1
gt University Card Service lt/h1gt lt/centergt lt!-
- TMPL_VAR NAME"content" --gt ltaddressgt Universit
y Card Interface provided by MISD. Please
contact the webmaster with any problems by email
lta href"mailtormc28_at_cam.ac.uk"gtrmc28_at_cam.ac.uklt
/agt lt/addressgt lt/bodygt lt/htmlgt
36HTMLTemplate example
!/usr/bin/perl -wT use strict use CGI use
HTMLTemplate my template
HTMLTemplate-gtnew(filename gt 'outer.tmpl') my
q CGI-gtnew template-gtparam( content gt
"Some content" ) print q-gtheader(
"text/html" ), template-gtoutput
37More than one template
!/usr/bin/perl -wT use strict use CGI use
HTMLTemplate my q CGI-gtnew my outer
HTMLTemplate-gtnew(filename gt 'outer.tmpl') my
content HTMLTemplate-gtnew(filename gt
'simple.tmpl') content-gtparam( fore gt
"Rachel", sur gt "Coleman" ) outer-gtparam(
content gt content-gtoutput ) print
q-gtheader( "text/html" ),
outer-gtoutput
simple.tmpl
ltpgt Forename lt!-- TMPL_VAR NAME"fore"
--gtltbrgt Surname lt!-- TMPL_VAR NAME"sur"
--gt lt/pgt
38More than one template
39Bringing in DBI
!/usr/bin/perl -wT use strict use CGI use
DBI use HTMLTemplate my attr (
PrintError gt 0, RaiseError gt 1, AutoCommit gt
0 ) my dbh DBI-gtconnect( "dbiOraclehostnnn
.nnn.nnn.nnnsidCARD", USER", PASS",
\attr ) or die (DBIerrstr, "\n") my q
CGI-gtnew my outer HTMLTemplate-gtnew(filenam
e gt 'outer.tmpl') my content
HTMLTemplate-gtnew(filename gt
'simple.tmpl') my ( sur, fore )
dbh-gtselectrow_array( " SELECT surname,
forenames FROM vw_cardholders WHERE
staff_number91540 " ) content-gtparam(
fore gt fore, sur gt sur ) outer-gtparam(
content gt content-gtoutput ) print
q-gtheader( "text/html" ), outer-gtoutput
40Bringing in DBI
41Using loops
table.tmpl
ltcentergt lttable border1gt lttrgt lt!-- TMPL_LOOP
NAME"header" --gt ltthgt lt!-- TMPL_VAR
NAMEheadval" --gt lt/thgt lt!-- /TMPL_LOOP --gt
lt/trgt lt!-- TMPL_LOOP NAME"data" --gt lttrgt
lt!-- TMPL_LOOP NAME"datavals" --gt lttdgt
lt!-- TMPL_VAR NAMEdatval" --gt lt/tdgt
lt!-- /TMPL_LOOP --gt lt/trgt lt!-- /TMPL_LOOP
--gt lt/tablegt lt/centergt
42Using loops
!/usr/bin/perl -wT use strict use CGI use
DBI use HTMLTemplate my attr (
PrintError gt 0, RaiseError gt 1, AutoCommit gt
0 ) my dbh DBI-gtconnect( "dbiOraclehostnnn
.nnn.nnn.nnnsidCARD", USER", PASS",
\attr ) or die (DBIerrstr, "\n") my q
CGI-gtnew my outer HTMLTemplate-gtnew(filenam
e gt 'outer.tmpl') my content
HTMLTemplate-gtnew(filename gt
'table.tmpl') my sth_hold dbh-gtprepare( "
SELECT cam_uid FROM vw_cardholders WHERE
surname 'Bolton' ORDER BY cam_uid " ) my
sth_card dbh-gtprepare( " SELECT
issue_number, photo_id, tdsi_number, expiry_date
FROM vw_cards WHERE cam_uid ? ORDER BY
issue_number " )
43Using loops cont.
my _at_header ( headval gt 'Card ID' ,
headval gt 'Issue' , headval gt 'Photo?' ,
headval gt 'TDSI?' , headval gt 'Expires'
) my ( uid, _at_data ) sth_hold-gtexecute st
h_hold-gtbind_col( 1, \uid ) while (
sth_hold-gtfetch ) my ( iss, phot, tdsi,
exp ) sth_card-gtbind_param( 1, uid )
sth_card-gtexecute sth_card-gtbind_columns(
\iss, \phot, \tdsi, \exp ) while (
sth_card-gtfetch ) my is_photo phot
(phot gt 0) ? "Y" "N" my
is_printed tdsi ? "Y" "N" my
_at_datavals ( datval gt uid ,
datval gt iss , datval gt is_photo ,
datval gt is_printed , datval gt exp
) push( _at_data, datavals gt
\_at_datavals ) content-gtparam( header
gt \_at_header, data gt \_at_data ) outer-gtparam(
content gt content-gtoutput ) print
q-gtheader( "text/html" ), outer-gtoutput
44Using loops
45Alternatives to HTMLTemplate
- CGI.pm
- Perl code produces HTML
- Embperl/Mason (other Perl modules)
- Parse Perl code embedded in HTML file
- Choose the approach that suits you
46Application states
- An application has states
- e.g. Edit gt Check gt Confirm
- But ... HTTP is stateless
- submit request, get output
- 3 choices for maintaining state
- query strings
- hidden fields
- cookies
47CGIApplication
- State managed by breaking code down into run
modes - Hidden field tells application which run-mode
its in - CGI script separate from main code
- Built-in support for HTMLTemplate
- Inherits from CGI.pm
- Documentation at CPAN
48CGIApplication
- Application example
- search for record
- display record
- edit record
- confirm changes
- gt 4 run modes
- Each run mode returns scalar variable holding
HTML page
49CGIApplication
!/usr/bin/perl -wT package RecordEdit use base
'CGIApplication' use DBI use strict sub
setup my self shift my dbh
DBI-gtconnect(blah) self-gtrun_modes(
'search' gt 'record_search', 'disp' gt
'record_show', 'edit' gt
'record_edit', 'conf' gt
'record_conf', ) self-gtstart_mode('start
') self-gtparam( 'mydbh' gt dbh ) sub
record_search my self shift my q
self-gtquery my template
self-load_tmpl('search.tmpl') ....
return template-gtoutput
sub record_show my self shift sub
record_edit my self shift sub
record_conf my self shift
recordedit.cgi
!/usr/bin/perl -w use strict use
RecordEdit my page RecordEdit-gtnew page-gtru
n
50Planning and doing
- Project management
- set a timetable
- you can control any 3 of time, cost, manpower and
quality - dont forget testing in your timetable
- start with at least an outline spec from users
- it is worth taking time on the spec but be
prepared for change
51University Card Service Web Access Card
Management
Show me the information regarding the cards in my
organisational Unit
Link a photo to an individual
Check on an individual card status
Add a person to the database
Inform the Card service that a card has been
stolen or lost
Request the removal of a connection
Request Temporary Cards
Trouble shooting options
52(No Transcript)
53Search
Photograph
Search!
View Photo No.
DOB
3 Letters
Reset!
Change to Photo No
Personal Information
Initials
Surname
Link Photo
Date of Birth
Forenames
Take Photo
Status
USN
ORGID
Progress
UID
Staff Number
Add!
Org Unit Source No. Source Title
Affiliations
Update!
1 of 4
Start End Actual Man?
Scarf? Revoke Revoke?
Add!
Issue Display Name Status Type Issued
Expire Photo TDSi
Cards
Update!
4 of 4
Man? Scarf Short BC Long BC Cam Bin
Revoke Revoke?
Add!
54(No Transcript)
55Planning and doing
- Aim to get something working quickly, and then
add functionality at intervals - Get users involved
- in specification
- while you are coding
- to try out updates
- Use version control (for your own sanity)
- (e.g. CVS http//cvshome.org)
56In summary...
- Be sure it needs to be done
- Consider security
- Perl these modules can make it easier but
- theres more than one way to do it in Perl
- there are alternatives to Perl
- Projects need managing
- and user interfaces need users