Docstoc

Web UI implementation with Perl

Document Sample
Web UI implementation with Perl Powered By Docstoc
					Implementing web user
  interfaces with Perl
      Rachel Coleman
 MISD-University Card Service
   University of Cambridge
 TechLink Seminar, 6 March 2002
                                  1
              Put it on the web!
• What you want to do         • How to do it
  –   What?                     – tools for CGI, DBI,
  –   Why?                        HTML, application
  –   For whom?                   building
  –   Security implications     – planning and doing




                                                        2
  What do you want to provide?
• View only (catalogue) ?
• Update access too (application)?




                                     3
   Why 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

                                                 4
Why 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


                                             5
Why 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


                                              6
        Who will be using it?
• Card office:
  – office staff (now), card reps (future)
• Other examples:
  – existing/potential students
  – researchers here/elsewhere
  – everyone!


                                             7
What 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



                                                          8
             Security - 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)



                                                 9
          Security - 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?


                                         10
             Before 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?

                                              11
                How 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
                                                 12
         Modules 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
  – don’t reinvent the wheel
                                           13
             Useful modules
•   CGI.pm
•   The Perl DBI
•   HTML::Template
•   CGI::Application




                              14
                    CGI.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/


                                              15
     CGI.pm example - generating HTML
#!/usr/bin/perl -w

use strict;
use CGI;

my $q = new CGI;

print $q->header( "text/html" ),
      $q->start_html( -title => "Great Rings of Power", -bgcolor => "#ffffcc" ),
      $q->center(
         $q->h1( "Ring allocation" ),
         $q->p( "The table below illustrates the allocation of the Great Rings of
                 power.” ),
         $q->table( {border => 1},
            $q->Tr( {align => "center"},
            [
            $q->th( [ 'Elves', 'Dwarf Lords', 'Mortal Men' ] ),
            $q->td( ['3','7','9'])
            ] )
         )
      ),
      $q->end_html;



                                                                                    16
CGI.pm example - generating HTML




                                   17
       CGI.pm example - generating HTML


<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html
          PUBLIC "-//W3C//DTD XHTML Basic 1.0//EN"
          "http://www.w3.org/TR/xhtml-basic/xhtml-basic10.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"><head><title>Great Rings of
Power</title>
</head><body bgcolor="#ffffcc"><center><h1>Ring allocation</h1> <p>The table below
illustrates the allocation of the Great Rings of power.</p> <table border="1"><tr
align="center"><th>Elves</th> <th>Dwarf Lords</th> <th>Mortal Men</th></tr> <tr
align="center"><td>3</td> <td>7</td> <td>9</td></tr></table></center></body></html>




 Source produced is messy - but that’s not what you work with



                                                                                      18
         CGI.pm example - accessing input
 #!/usr/bin/perl -w

 use strict;
 use CGI;

 my $q = new CGI;

 my $forename = $q->param('forename');
 my $surname = $q->param('surname');

 print   $q->header( "text/html" ),
     $q->start_html( -title => "People", -bgcolor => "#ffffcc" ),
     $q->center(
         $q->p( "The following values were received:" ),
         $q->p( "Surname: $surname" ),
         $q->p( "Forename: $forename" )
         ),
     $q->end_html;




Parameters supplied, e.g. in query string:
https://10.0.12.3/~rachel/cgi/sample2.cgi?surname=Baggins&forename=Bilbo
                                                                    19
CGI.pm example - accessing input




                                   20
              CGI.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->param('surname') =~ /^([a-zA-Z]+)$/;

print   $q->header( "text/html" ),
    $q->start_html( -title => "People", -bgcolor => "#ffffcc" ),
    $q->center(
        $q->p( "The following values were received:" ),
        $q->p( "Surname: $surname" ),
        ),
    $q->end_html;
                                                                   21
CGI.pm example - Taint mode




my ( $surname ) = $q->param('surname') =~ /^([a-zA-Z]+)$/;




                                                             22
CGI.pm example - Taint mode




my ( $surname ) = $q->param('surname') =~ /^([a-zA-Z]+)$/;




                                                             23
            Why 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

                                                          24
              The Perl DBI
• Simple high-level interface to any database




             Diagram reproduced courtesy of Alligator Descartes

                                                                  25
                   DBI
• 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
                                           26
              DBI example - simple fetch
#!/usr/bin/perl -w                                  [rachel@apollo talk]$ perl dbi1.pl
                                                    'Coleman', 'Andrew Thomas Guy'
use strict;                                         'Coleman', 'Anthony Patrick'
use DBI;                                            'Coleman', 'Eliza'
                                                    'Coleman', 'Gillian Mary'
my %attr = (                                        'Coleman', 'Heather Margaret'
    PrintError => 0,                                'Coleman', 'Jamie'
    RaiseError => 1,                                'Coleman', 'Jonathan David'
    AutoCommit => 0                                 'Coleman', 'Martin Richard'
);                                                  'Coleman', 'Nicholas'
                                                    'Coleman', 'Pamela Ashleigh'
my $dbh = DBI->connect( ”                           'Coleman', 'Rachel Mary'
    dbi:Oracle:host=nnn.nnn.nnn.nnn;sid=CARD"       'Coleman', 'Sam Joseph'
    “USER", ”PASSWORD", \%attr                      'Coleman', 'Thomas McKinney'
    ) or die ( $DBI::errstr, "\n");                 'Coleman', 'Thomas William'
                                                    'Coleman', 'Toby John'
my $sth = $dbh->prepare( "                          'Coleman', 'Toby William'
    SELECT surname, forenames FROM vw_cardholders   16 rows
    WHERE surname = 'Coleman'                       [rachel@apollo talk]$
    ORDER BY forenames
    " );

$sth->execute;
$sth->dump_results;

$dbh->disconnect;

                                                                                  27
            DBI example - line-at-time

my $sth = $dbh->prepare( "                          [rachel@apollo talk]$ perl dbi2.pl
    SELECT surname, forenames FROM vw_cardholders   Andrew Thomas Guy Coleman
    WHERE surname = 'Coleman'                       Anthony Patrick Coleman
    ORDER BY forenames                              Eliza Coleman
    " );                                            Gillian Mary Coleman
                                                    Heather Margaret Coleman
my ( $sur, $fore );                                 Jamie Coleman
$sth->execute;                                      Jonathan David Coleman
                                                    Martin Richard Coleman
while ( $sur, $fore ) = $sth->fetchrow_array ) {    Nicholas Coleman
    print "$forenames $surname\n";                  Pamela Ashleigh Coleman
}                                                   Rachel Mary Coleman
                                                    Sam Joseph Coleman
$dbh->disconnect;                                   Thomas McKinney Coleman
                                                    Thomas William Coleman
                                                    Toby John Coleman
                                                    Toby William Coleman
                                                    [rachel@apollo talk]$




                                                                                 28
         DBI example - atomic fetch
my @results = $dbh->selectrow_array( "
    SELECT * FROM vw_cardholders WHERE surname='Coleman' AND forenames like 'Rachel%'
    " );

foreach my $field ( @results ) {
    $field = "" unless $field;
    print "$field\n";
}

$dbh->disconnect;


[rachel@apollo talk]$ perl dbi3.pl
rc0153f
Rachel Mary
Coleman
28-JUN-77
91540

nl219

153

48866

[rachel@apollo talk]$
                                                                                  29
Binding columns and bind values
my $sth_hold = $dbh->prepare( "
    SELECT cam_uid FROM vw_cardholders WHERE surname = ’Bolton' ORDER BY cam_uid
    " );

my $sth_card = $dbh->prepare( "
    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?\tTDSI\tExpires?\n";

$sth_hold->execute;
$sth_hold->bind_col( 1, \$uid );

while ( $sth_hold->fetch ) {
    my ( $iss, $phot, $tdsi, $exp );
    $sth_card->bind_param( 1, $uid );
    $sth_card->execute;
    $sth_card->bind_columns( \$iss, \$phot, \$tdsi, \$exp );
    while ( $sth_card->fetch ) {
        my $is_photo = $phot && ($phot > 0) ? "Y" : "N";
        my $is_printed = $tdsi ? "Y" : "N";
        print "$uid\t$iss\t$is_photo\t$is_printed\t$exp\n";
    }
}
                                                                               30
Binding columns and bind values
      [rachel@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@apollo talk]$


                                                  31
           HTML::Template
• Adds the following to HTML
  – variables
  – loops
  – if-then-else
• Allows separation of page design and code
  design
• Allows component reuse

                                              32
33
34
HTML::Template example
                     outer.tmpl
 <!doctype html public "-//w3c//dtd html 4.01 Frameset//en"
                     "http://www.w3.org/TR/html4/frameset.dtd">
 <head>
    <title>University Card Interface</title>
 </head>

 <body bgcolor="#99ccff" text="#000000" link="#3300cc"
       alink="#ff0000" vlink="#990066">
 <center>
 <h1>
     University Card Service
 </h1>
 </center>

 <!-- TMPL_VAR NAME="content" -->

 <address>
 University Card Interface provided by MISD.
 Please contact the webmaster with any problems by email:
 <a href="mailto:rmc28@cam.ac.uk">rmc28@cam.ac.uk</a>
 </address>

 </body>
 </html>
                                                                  35
HTML::Template example
#!/usr/bin/perl -wT

use strict;
use CGI;
use HTML::Template;

my $template = HTML::Template->new(filename => 'outer.tmpl');
my $q = CGI->new;

$template->param( content => "Some content" );

print   $q->header( "text/html" ),
        $template->output;




                                                                36
            More than one template
#!/usr/bin/perl -wT

use strict;
use CGI;
use HTML::Template;

my $q = CGI->new;
my $outer = HTML::Template->new(filename => 'outer.tmpl');
my $content = HTML::Template->new(filename => 'simple.tmpl');

$content->param( fore => "Rachel", sur => "Coleman" );
$outer->param( content => $content->output );

print   $q->header( "text/html" ),
        $outer->output;



simple.tmpl
<p>
Forename: <!-- TMPL_VAR NAME="fore" --><br>
Surname: <!-- TMPL_VAR NAME="sur" -->
</p>
                                                                37
More than one template




                         38
                        Bringing in DBI
#!/usr/bin/perl -wT

use   strict;
use   CGI;
use   DBI;
use   HTML::Template;

my %attr = (
    PrintError => 0, RaiseError => 1, AutoCommit => 0
);

my $dbh = DBI->connect( "dbi:Oracle:host=nnn.nnn.nnn.nnn;sid=CARD", ”USER", ”PASS",
                        \%attr ) or die ($DBI::errstr, "\n");

my $q = CGI->new;

my $outer = HTML::Template->new(filename => 'outer.tmpl');
my $content = HTML::Template->new(filename => 'simple.tmpl');

my ( $sur, $fore ) = $dbh->selectrow_array( "
    SELECT surname, forenames FROM vw_cardholders WHERE staff_number=91540
    " );

$content->param( fore => $fore, sur => $sur );
$outer->param( content => $content->output );

print     $q->header( "text/html" ),
          $outer->output;
                                                                                 39
Bringing in DBI




                  40
  Using loops
         table.tmpl
<center>
<table border=1>
    <tr>
<!-- TMPL_LOOP NAME="header" -->
    <th>
         <!-- TMPL_VAR NAME=”headval" -->
    </th>
<!-- /TMPL_LOOP -->
    </tr>
<!-- TMPL_LOOP NAME="data" -->
    <tr>
    <!-- TMPL_LOOP NAME="datavals" -->
    <td>
         <!-- TMPL_VAR NAME=”datval" -->
    </td>
    <!-- /TMPL_LOOP -->
    </tr>
<!-- /TMPL_LOOP -->
</table>
</center>


                                            41
                            Using loops
#!/usr/bin/perl -wT

use   strict;
use   CGI;
use   DBI;
use   HTML::Template;

my %attr = (
    PrintError => 0, RaiseError => 1, AutoCommit => 0
);

my $dbh = DBI->connect( "dbi:Oracle:host=nnn.nnn.nnn.nnn;sid=CARD", ”USER", ”PASS",
                        \%attr ) or die ($DBI::errstr, "\n");

my $q = CGI->new;

my $outer = HTML::Template->new(filename => 'outer.tmpl');
my $content = HTML::Template->new(filename => 'table.tmpl');

my $sth_hold = $dbh->prepare( "
    SELECT cam_uid FROM vw_cardholders WHERE surname = 'Bolton' ORDER BY cam_uid
    " );

my $sth_card = $dbh->prepare( "
    SELECT issue_number, photo_id, tdsi_number, expiry_date
    FROM vw_cards WHERE cam_uid = ? ORDER BY issue_number
    " );
                                                                                   42
                  Using loops cont.
my @header = (
    { headval => 'Card ID' }, { headval => 'Issue' }, { headval => 'Photo?' },
    { headval => 'TDSI?' }, { headval => 'Expires' } );

my ( $uid, @data );

$sth_hold->execute;
$sth_hold->bind_col( 1, \$uid );

while ( $sth_hold->fetch ) {
    my ( $iss, $phot, $tdsi, $exp );
    $sth_card->bind_param( 1, $uid );
    $sth_card->execute;
    $sth_card->bind_columns( \$iss, \$phot, \$tdsi, \$exp );
    while ( $sth_card->fetch ) {
        my $is_photo = $phot && ($phot > 0) ? "Y" : "N";
        my $is_printed = $tdsi ? "Y" : "N";
        my @datavals = (
            { datval => $uid },{ datval => $iss }, { datval => $is_photo },
            { datval => $is_printed }, { datval => $exp } );
        push( @data, { datavals => \@datavals } );
    }
}

$content->param( header => \@header, data => \@data );
$outer->param( content => $content->output );

print   $q->header( "text/html" ), $outer->output;                               43
Using loops




              44
Alternatives to HTML::Template
• CGI.pm
  – Perl code produces HTML
• Embperl/Mason (other Perl modules)
  – Parse Perl code embedded in HTML file
• Choose the approach that suits you



                                            45
           Application states
• An application has states
  – e.g. Edit => Check => Confirm
• But ... HTTP is stateless
  – submit request, get output
• 3 choices for maintaining state:
  – query strings
  – hidden fields
  – cookies
                                     46
           CGI::Application
• State managed by breaking code down into
  ‘run modes’
• Hidden field tells application which run-
  mode it’s in
• CGI script separate from main code
• Built-in support for HTML::Template
• Inherits from CGI.pm
• Documentation at CPAN                     47
             CGI::Application
• Application example:
  –   search for record
  –   display record
  –   edit record
  –   confirm changes
  –   => 4 run modes
• Each run mode returns scalar variable
  holding HTML page
                                          48
                      CGI::Application
#!/usr/bin/perl -wT                                  sub record_show {
                                                         my $self = shift;
package RecordEdit;
use base 'CGI::Application';                         }
use DBI;
use strict;                                          sub record_edit {
                                                         my $self = shift;
sub setup {
    my $self = shift;                                }
    my $dbh = DBI->connect(blah);
    $self->run_modes(                                sub record_conf {
        'search' => 'record_search',                     my $self = shift;
        'disp'   => 'record_show',
        'edit'   => 'record_edit',                   }
        'conf'   => 'record_conf',
    );
    $self->start_mode('start');                      recordedit.cgi
    $self->param( 'mydbh' => $dbh );
}
                                                     #!/usr/bin/perl -w
sub record_search {
                                                     use strict;
    my $self = shift;
                                                     use RecordEdit;
    my $q = $self->query;
    my $template = $self-load_tmpl('search.tmpl');
                                                     my $page = RecordEdit->new;
    ....
                                                     $page->run;
    return $template->output;
}                                                                             49
          Planning and doing
• Project management:
  – set a timetable
  – you can control any 3 of time, cost, manpower
    and quality
  – don’t 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
                                                     50
                                University Card Service
                                     Web Access

                                     Card Management


       Show me the information regarding
                                                Link a photo to an individual
       the cards in my organisational Unit



        Check on an individual card status     Add a person to the database



          Inform the Card service that a            Request the removal
           card has been stolen or lost               of a connection


            Request Temporary Cards




Trouble shooting options                                                        51
52
                                             Search                                             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
ORGID           USN                 Status
                                                            Progress

UID             Staff Number
                                       Add!


 Org Unit   Source No.    Source    Title                                                       Affiliations
                                                                            1         Update!
  Start         End       Actual    Man? Scarf? Revoke      Revoke?         of
                                                                            4          Add!


Issue Display Name        Status Type Issued       Expire      Photo TDSi
                                                                                                    Cards
                                                                                 4    Update!
Man? Scarf Short BC       Long BC    Cam Bin   Revoke        Revoke?
                                                                                 of
                                                                                 4     Add!        53
54
         Planning 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)
                                              55
              In summary...
• Be sure it needs to be done
• Consider security
• Perl & these modules can make it easier but
  – there’s more than one way to do it in Perl
  – there are alternatives to Perl
• Projects need managing
  – and user interfaces need users

                                                 56

				
DOCUMENT INFO
Shared By:
Categories:
Tags:
Stats:
views:47
posted:8/6/2011
language:English
pages:56