Customize Pages with CGI

CGI can show different pages to different users depending on user preferences.

Exercise:

1) Ask a user to input their name into a textfield and to choose a color from a popup menu. Then display a page with a short message (e.g. "Thank you $name for your request") in that color.

Security on CGI Pages

There are several security problems and error sources for CGI scripts such as the one above.

Here are some security tips:

The following tips are listed here for completeness. You'll understand them when environment variables are discussed in a couple of weeks. More information on security of CGI scripts, Perl/CGI and general WWW security

Exercises

2) In the previous script check whether the input is reasonable and not empty:
- check whether the name and color contain only word characters or -.
- check that neither name nor color is longer than 100 chars (use the {100,} multiplier).
If the criteria are not fulfilled, do not display the results page but instead show an error message.
3) For the $name variable replace HTML characters "<" and ">" with &#60; and &#62; before printing the name.

Searching a Webpage

The following CGI script expects a URL and a keyword as input from a form.

#!/usr/local/bin/perl -w
use IO::Socket;
use CGI qw(:standard);

############# beginning of main routine ####################

my $url = param("url");
my $keyword = param("keyword");

start_webpage();
($host, $document) = parse_input($url);
@page_content= read_page($host,$document);
search($keyword, @page_content);

############## end of main routine ###########################

sub start_webpage{
print header();
print "<HTML>
<HEAD>
<TITLE>Search Results</TITLE>
</HEAD>
<BODY>
<H3>Search Results</h3>"
}

##############################################################

sub parse_input {
    $current_url = $_[0];
    $current_url =~ /(http:\/\/)?([^\/]*)(.*)/;
    $host = $2;
    $document = $3;
    if ($document eq "") {$document = "/";}
    return ($host, $document);
}

########################################################################

sub read_page{
    my $current_host=$_[0];
    my $current_doc=$_[1];
    $remote =IO::Socket::INET->new(Proto => "tcp",
    PeerAddr => $current_host,
    PeerPort => "http(80)",
    );
    if (!$remote) { die "cannot connect to http daemon on $host"}
    $remote->autoflush(1);
    print $remote "GET $current_doc HTTP/1.0\n\n";
    @output = <$remote> ;
    close $remote;
    return @output;
}

##################################################################
sub search{
    ($term,@text) = @_;
    print "<p>The results for $term are:";
    print @text;
}

Exercises

4) Write a form that lets users input a URL and a keyword and invokes the CGI script.
5) Change the subroutine "search" so that it actually searches for the keyword and prints the lines that contain the keyword.

Optional: Less typing

The CGI.pm module provides standard subroutines for printing certain HTML code fragments. For example, print h1("Tea"); prints an h1 header. To use these subroutines, the script must contain the line "use CGI qw(:standard);".

Abbreviations for writing HTML tags

  • print header();
  • print start_html(-title=>"title_goes_here",-BGCOLOR=>'yellow');
  • print h1("some heading");
  • print hr();
  • print p("text");
  • print start_form();
  • print a({href=>"url_goes_here.html"},"link text goes here");
  • print textfield(-name=>'field_name',-default=>'starting value', -size=>50,-maxlength=>80);
  • print textarea(-name=>'foo',-default=>'starting value',-rows=>10, -columns=>50);
  • print password_field(-name=>'secret',-value=>'starting value', -size=>50, -maxlength=>80);
  • print popup_menu(-name=>'menu_name',-values=>['one','two','three'], -default=>'two');
  • print scrolling_list(-name=>'list_name',-values=>['one','two','three'], -default=>['one','three'];-size=>3, -multiple=>'true', -labels=>\%labels);
  • print checkbox_group(-name=>'group_name',-values=>['one','two','three'], -default=>['one','three'],-linebreak=>'true',-labels=>\%labels);
  • print checkbox(-name=>'checkbox_name', -checked=>'checked', -value=>'TURNED ON', -label=>'Turn me on');
  • print radio_group(-name=>'group_name',-values=>['one','two','three'], -default=>'one', -linebreak=>'true', -labels=>\%labels);
  • print submit(-name=>'button_name', -value=>'value');
  • print hidden(-name=>'hidden_name', -default=>['value1','value2']);
  • print reset();
  • print end_form();