DCPM Jan 4 2000
Lisa Nyman, US Census Bureau

The CGI.pm module provides methods for doing most all HTML/CGI work.

Features

  • Create forms and parse form input
  • Saving the state of the form
  • Cookies
  • Session variable methods
  • Support for frames
  • Support for JavaScript
  • Limited Support for Cascading Style Sheets
  • File Upload

    Here is a simple example of a page created with CGI.pm (Object-oriented mode):

    #!/usr/local/bin/perl5use CGI; # create new CGI object $page = new CGI;

    # create standard HTTP and HTML document headers print $page­>header(); print $page­>start_html(­title=>'Sample Web Page', -bgcolor=>'#FFFFFF', ­script=>{­language=>'JavaScript', ­src=>'/path/file.js'});

    # print form with text entry field for name and submit and reset buttons print $page­>h3("Sample Page"); print $page­>startform(­method=>'POST', ­action=>'/cgi­bin/action.pl'); print "Enter your name: \n"; print $page­>textfield(­name=>'Name', ­size=>60); print $page­>submit(­value=>'Send'); print $page­>reset(­value=>'Clear selections'); # end form and HTML document print $page­>endform; print $page­>end_html;

    The script processing the action from the form looks like this:

    #!/usr/local/bin/perl
    #Program Name: action.pl
    use CGI;
    

    # create new CGI object $page = new CGI;

    # create standard HTTP and HTML document headers print $page­>header(); print $page­>start_html(­title=>'Sample Web Page Result', ­bgcolor=>'#FFFFFF'); print $page­>h3("Sample Page Result");

    # fetch the value of 'Name' passed to the script $user_name = $page­>param('Name'); print "Hello, $user_name!\n"; print $page­>end_html;

    These two programs can be combined into a single script: #!/usr/local/bin/perl5 use CGI; # create new CGI object $page = new CGI;

    # create standard HTTP and HTML document headers print page­>header(); print $page­>start_html(­title=>'Sample Web Page', ­bgcolor=>'#FFFFFF', ­script=>{­language=>'JavaScript', ­src=>'/path/file.js'}); print $page­>h3("Sample Page");

    # if a value for Name is passed to the script, print results # else print form if ($user_name = $page­>param('Name')) { print $page­>h3("Sample Page Result"); print "Hello, $user_name!\n"; } else { print $page­>startform(­method=>'POST'); print "Enter your name: \n"; print $page­>textfield(­name=>'Name', ­size=>60); print $page­>submit(­value=>'Send'); print $page­>reset(­value=>'Clear selections'); print $page­>endform; } print $page­>end_html;

    In the last example, no action program is specified when the form begins. The form issubmitted to the same script that created it. The program then decides what course to follow (am I the action this time?) based on the value of any form variables which are fetched by the param() function. This feature allows for sticky forms.

    Some Methods

    $page = new CGI$page­>textfield(­name=>'Agency', ­size=>25, -value=>'Census') $page­>br $cookie2 = $page­>cookie(­name=>'phone', ­value=>'2150', -expires=>'+365d',­path=>'/', ­domain=>'.census.gov') $page­>header(­cookie=>[$cookie, $cookie2]) $page­>radio_group(­name=>'Mail', ­values=>['quickmail', 'microsoft'], ­default=>'none', ­linebreak=>1, ­labels=>{'microsoft'=>'Microsoft Internet Mail', 'quickmail'=>'QuickMail'}) $page­>submit(­value=>'Submit answers')

    Sticky Forms

    A sticky form is one that maintains its state (in other words, the values stick). The value ofthe previous form fields are used to initialize the current form fields of the same name. The state of the form is preserved from invocation to invocation. The default values specified for the forms are only used the first time the script is invoked.

    Suppose the following code logic:

    begin page    
    if (name was filled in)
    	but if (no email) ask 'User' for email
      else say hello 'User' and thanks for email
    else print form to get user name and email input
    end page
    

    In this case, Jane fills in her name, and after submitting the form, gets back:

    Hello, Jane! I need your email, too!
    Enter your Email:

    While this is a trivial example, imagine instead a form with 20 fields and after checking forminput on the server side, the program can print accepted form elements again with the savedvalues.

    begin page if (form was filled in) validate required fields (server-side) print form again for the user if there is an input error else process the form else print form to get user input end page

    Why is this a good feature? Why can't the user just use the back button to get the originalform and input? All browsers do not maintain filled form fields. The sticky forms feature can be turned off if necessary with the ­override=>1 directive. 'Sticky values' also let you use a single script to build a multi-part form based on previousinput.

    Two ways to use CGI.pm

    1. Function oriented mode

    Import CGI functions into your script's namespace, then call these functions directly.

    #!/usr/local/bin/perl
    use CGI qw/:standard/;
    print header(),
      start_html(­title=>'Wow!'),
      h1('Wow!'),
      'Look Ma, no hands!',
      end_html();
    

    Good for scripts using a single CGI object Implicit CGI object CGI::Q 8 method families available for importing. The example below imports cgi method family.

    #!/usr/local/bin/perl	# a little redirection action script 
    # (could use redirection header, too)
    
    use CGI qw/:cgi/;
    $server = server_name();	
    $location = param('Location');	
    print qq!Location: http://$server/$location\n\n!;
    exit;
    

    2. Object-oriented mode

    In the object­oriented mode, you use CGI; without specifying any functions or function sets to import. In this case, you communicate with CGI.pm via a CGI object.

    #!/usr/local/bin/perl
    use CGI;
    $q = new CGI;
    print $q­>header(),
      $q­>start_html(­title=>'Wow!'),
      $q­>h1('Wow!'),
      'Look Ma, no hands!',
      $q­>end_html();
    

    Some Special Features

    1. Maximum form data size

    Using CGI.pm, you can prevent some types of server attacks using the $CGI::POST_MAX variable. This variable sets the maximum size of return data from a form that you are willing to accept. Using this variable replaces checking content_length by hand.

    Why do you want to do this? Say you have a simple guestbook form that takes user input and writes it to a guestbook file on your server. Well, nothing prevents Mr. Evil from filling in your form with tons of info, submitting the form 100 times, thereby filling up your disk and crashing your server.

    But you say "I set the MAXSIZE attribute on my text input box." Well, remember, no law says your CGI script has to be called from your form. I copy your form onto my local server leaving the action as your CGI, change a few things here and there, and bingo ­ I have a great attack waiting to happen. Clickety­click...fill disk...crash. Of course scripts should handle Out of Disk Space errors when writing to files, too.

    Here is a code snippet:

    
    $CGI::POST_MAX=1024 * 10;     # max 10K posts	
    $run = $page­>param('RUN');   # grab a form variable
    if (!$run && cgi_error()) {   # if the variable is empty 
    			      # BUT we have a cgi_error -        	
        dieWell('Oops: $!');      # handle the error        	
        }
    

    BTW, cgi_error will return a 413 error: Request Entity Too Large. A note on dyeing gracefully: A lot of people use CGI::Carp which has error message methods, log enhancements, etc. The CGI::Carp 'fatalsToBrowser' subroutine [use CGI::Carpqw(fatalsToBrowser);] will echo error messages to the browser window and proved HTTPheaders so internal errors will not obliterate your application.

    2. cgi-lib.pl conversion

    CGI.pm provides a CGI::ReadParse() call that is compatible with cgi­lib.pl's ReadParse() subroutine. ReadParse() creates an associative array named %in that contains the named CGI parameters. use CGI qw(:cgi­lib); ReadParse(); %in now holds the form variables. Use a variable glob if you want a different variable thanthe default "%in". ReadParse(*form);

    3. File Upload

    To use the file upload method, call the new start_multipart_form() method which results in:

    <FORM METHOD="POST" ENCTYPE="multipart/form­data">.

    Without 'multipart' encoding type, you'll be able to retrieve the name of the file selected forupload, but you won't be able to access its contents.

    #!/usr/local/bin/perl5
    use CGI qw(:standard);
    
    print header(),
    start_html(­title=>'File Upload'),
    start_multipart_form,
    filefield(­name=>'uploaded_file',­size=>50,­maxlength=>80),
    end_form(),
    end_html();
    
    

    param('uploaded_file') returns the contents of the file. If used as a string, the returned valueis the file name. Treat the returned value as a file handle to read the contents of the file.

    Resources

    Official Guide to Programming with CGI.pm: The Standard for Building Web Scripts By Lincoln D. Stein April, 1998. John Wiley & Sons, Inc.

    CGI.pm ­ a Perl5 CGI Library http://stein.cshl.org/WWW/software/CGI/cgi_docs.html