http://www.perlmonks.org?node_id=1312

lib

Current Perl documentation can be found at perldoc.perl.org.

Here is our local, out-dated (pre-5.6) version:

CREATING A FILE UPLOAD FIELD

    print $query->filefield(-name=>'uploaded_file',
                            -default=>'starting value',
                            -size=>50,
                            -maxlength=>80);
        -or-

    print $query->filefield('uploaded_file','starting value',50,80);

filefield() will return a file upload field for Netscape 2.0 browsers. In order to take full advantage of this you must use the new multipart encoding scheme for the form. You can do this either by calling startform() with an encoding type of $CGI::MULTIPART, or by calling the new method start_multipart_form() instead of vanilla startform().

Parameters
  • .

    The first parameter is the required name for the field (-name).

  • . The optional second parameter is the starting value for the field contents to be used as the default file name (-default).

    The beta2 version of Netscape 2.0 currently doesn't pay any attention to this field, and so the starting value will always be blank. Worse, the field loses its ``sticky'' behavior and forgets its previous contents. The starting value field is called for in the HTML specification, however, and possibly later versions of Netscape will honor it.

  • . The optional third parameter is the size of the field in characters (-size).

  • . The optional fourth parameter is the maximum number of characters the field will accept (-maxlength).
  • When the form is processed, you can retrieve the entered filename by calling param().

           $filename = $query->param('uploaded_file');
    

    In Netscape Navigator 2.0, the filename that gets returned is the full local filename on the remote user's machine. If the remote user is on a Unix machine, the filename will follow Unix conventions:

            /path/to/the/file
    

    On an MS-DOS/Windows and OS/2 machines, the filename will follow DOS conventions:

            C:\PATH\TO\THE\FILE.MSW
    

    On a Macintosh machine, the filename will follow Mac conventions:

            HD 40:Desktop Folder:Sort Through:Reminders
    

    The filename returned is also a file handle. You can read the contents of the file using standard Perl file reading calls:

            # Read a text file and print it out
            while (<$filename>) {
               print;
            }
    

            # Copy a binary file to somewhere safe
            open (OUTFILE,">>/usr/local/web/users/feedback");
            while ($bytesread=read($filename,$buffer,1024)) {
               print OUTFILE $buffer;
            }
    

    When a file is uploaded the browser usually sends along some information along with it in the format of headers. The information usually includes the MIME content type. Future browsers may send other information as well (such as modification date and size). To retrieve this information, call uploadInfo(). It returns a reference to an associative array containing all the document headers.

           $filename = $query->param('uploaded_file');
           $type = $query->uploadInfo($filename)->{'Content-Type'};
           unless ($type eq 'text/html') {
              die "HTML FILES ONLY!";
           }
    

    If you are using a machine that recognizes ``text'' and ``binary'' data modes, be sure to understand when and how to use them (see the Camel book). Otherwise you may find that binary files are corrupted during file uploads.

    JAVASCRIPTING: The -onChange, -onFocus, -onBlur, -onMouseOver, -onMouseOut and -onSelect parameters are recognized. See textfield() for details.

    CREATING A POPUP MENU

       print $query->popup_menu('menu_name',
                                ['eenie','meenie','minie'],
                                'meenie');
    

          -or-
    

       %labels = ('eenie'=>'your first choice',
                  'meenie'=>'your second choice',
                  'minie'=>'your third choice');
       print $query->popup_menu('menu_name',
                                ['eenie','meenie','minie'],
                                'meenie',\%labels);
    

            -or (named parameter style)-
    

       print $query->popup_menu(-name=>'menu_name',
                                -values=>['eenie','meenie','minie'],
                                -default=>'meenie',
                                -labels=>\%labels);
    

    popup_menu() creates a menu.

    1. .

      The required first argument is the menu's name (-name).

    2. . The required second argument (-values) is an array reference containing the list of menu items in the menu. You can pass the method an anonymous array, as shown in the example, or a reference to a named array, such as ``\@foo''.

    3. . The optional third parameter (-default) is the name of the default menu choice. If not specified, the first item will be the default. The values of the previous choice will be maintained across queries.

    4. . The optional fourth parameter (-labels) is provided for people who want to use different values for the user-visible label inside the popup menu nd the value returned to your script. It's a pointer to an associative array relating menu values to user-visible labels. If you leave this parameter blank, the menu values will be displayed by default. (You can also leave a label undefined if you want to).

    When the form is processed, the selected value of the popup menu can be retrieved using:

          $popup_menu_value = $query->param('menu_name');
    

    JAVASCRIPTING: popup_menu() recognizes the following event handlers: -onChange, -onFocus, -onMouseOver, -onMouseOut, and -onBlur. See the textfield() section for details on when these handlers are called.

    CREATING A SCROLLING LIST

       print $query->scrolling_list('list_name',
                                    ['eenie','meenie','minie','moe'],
                                    ['eenie','moe'],5,'true');
          -or-
    

       print $query->scrolling_list('list_name',
                                    ['eenie','meenie','minie','moe'],
                                    ['eenie','moe'],5,'true',
                                    \%labels);
    

            -or-
    

       print $query->scrolling_list(-name=>'list_name',
                                    -values=>['eenie','meenie','minie','moe'],
                                    -default=>['eenie','moe'],
                                    -size=>5,
                                    -multiple=>'true',
                                    -labels=>\%labels);
    

    scrolling_list() creates a scrolling list.

    Parameters:
  • .

    The first and second arguments are the list name (-name) and values (-values). As in the popup menu, the second argument should be an array reference.

  • . The optional third argument (-default) can be either a reference to a list containing the values to be selected by default, or can be a single value to select. If this argument is missing or undefined, then nothing is selected when the list first appears. In the named parameter version, you can use the synonym ``-defaults'' for this parameter.

  • . The optional fourth argument is the size of the list (-size).

  • . The optional fifth argument can be set to true to allow multiple simultaneous selections (-multiple). Otherwise only one selection will be allowed at a time.

  • . The optional sixth argument is a pointer to an associative array containing long user-visible labels for the list items (-labels). If not provided, the values will be displayed.

    When this form is processed, all selected list items will be returned as a list under the parameter name 'list_name'. The values of the selected items can be retrieved with:

          @selected = $query->param('list_name');
    
  • JAVASCRIPTING: scrolling_list() recognizes the following event handlers: -onChange, -onFocus, -onMouseOver, -onMouseOut and -onBlur. See textfield() for the description of when these handlers are called.

    CREATING A GROUP OF RELATED CHECKBOXES

       print $query->checkbox_group(-name=>'group_name',
                                    -values=>['eenie','meenie','minie','moe'],
                                    -default=>['eenie','moe'],
                                    -linebreak=>'true',
                                    -labels=>\%labels);
    

       print $query->checkbox_group('group_name',
                                    ['eenie','meenie','minie','moe'],
                                    ['eenie','moe'],'true',\%labels);
    

       HTML3-COMPATIBLE BROWSERS ONLY:
    

       print $query->checkbox_group(-name=>'group_name',
                                    -values=>['eenie','meenie','minie','moe'],
                                    -rows=2,-columns=>2);
        
    

    checkbox_group() creates a list of checkboxes that are related by the same name.

    Parameters:
  • .

    The first and second arguments are the checkbox name and values, respectively (-name and -values). As in the popup menu, the second argument should be an array reference. These values are used for the user-readable labels printed next to the checkboxes as well as for the values passed to your script in the query string.

  • . The optional third argument (-default) can be either a reference to a list containing the values to be checked by default, or can be a single value to checked. If this argument is missing or undefined, then nothing is selected when the list first appears.

  • . The optional fourth argument (-linebreak) can be set to true to place line breaks between the checkboxes so that they appear as a vertical list. Otherwise, they will be strung together on a horizontal line.

  • . The optional fifth argument is a pointer to an associative array relating the checkbox values to the user-visible labels that will be printed next to them (-labels). If not provided, the values will be used as the default.

  • . HTML3-compatible browsers (such as Netscape) can take advantage of the optional parameters -rows, and -columns. These parameters cause checkbox_group() to return an HTML3 compatible table containing the checkbox group formatted with the specified number of rows and columns. You can provide just the -columns parameter if you wish; checkbox_group will calculate the correct number of rows for you.

    To include row and column headings in the returned table, you can use the -rowheaders and -colheaders parameters. Both of these accept a pointer to an array of headings to use. The headings are just decorative. They don't reorganize the interpretation of the checkboxes -- they're still a single named unit.

  • When the form is processed, all checked boxes will be returned as a list under the parameter name 'group_name'. The values of the ``on'' checkboxes can be retrieved with:

          @turned_on = $query->param('group_name');
    

    The value returned by checkbox_group() is actually an array of button elements. You can capture them and use them within tables, lists, or in other creative ways:

        @h = $query->checkbox_group(-name=>'group_name',-values=>\@values);
        &use_in_creative_way(@h);
    

    JAVASCRIPTING: checkbox_group() recognizes the -onClick parameter. This specifies a JavaScript code fragment or function call to be executed every time the user clicks on any of the buttons in the group. You can retrieve the identity of the particular button clicked on using the ``this'' variable.

    CREATING A STANDALONE CHECKBOX

        print $query->checkbox(-name=>'checkbox_name',
                               -checked=>'checked',
                               -value=>'ON',
                               -label=>'CLICK ME');
    

            -or-
    

        print $query->checkbox('checkbox_name','checked','ON','CLICK ME');
    

    checkbox() is used to create an isolated checkbox that isn't logically related to any others.

    Parameters:
  • .

    The first parameter is the required name for the checkbox (-name). It will also be used for the user-readable label printed next to the checkbox.

  • . The optional second parameter (-checked) specifies that the checkbox is turned on by default. Synonyms are -selected and -on.

  • . The optional third parameter (-value) specifies the value of the checkbox when it is checked. If not provided, the word ``on'' is assumed.

  • . The optional fourth parameter (-label) is the user-readable label to be attached to the checkbox. If not provided, the checkbox name is used.
  • The value of the checkbox can be retrieved using:

        $turned_on = $query->param('checkbox_name');
    

    JAVASCRIPTING: checkbox() recognizes the -onClick parameter. See checkbox_group() for further details.

    CREATING A RADIO BUTTON GROUP

       print $query->radio_group(-name=>'group_name',
                                 -values=>['eenie','meenie','minie'],
                                 -default=>'meenie',
                                 -linebreak=>'true',
                                 -labels=>\%labels);
    

            -or-
    

       print $query->radio_group('group_name',['eenie','meenie','minie'],
                                              'meenie','true',\%labels);
    

       HTML3-COMPATIBLE BROWSERS ONLY:
    

       print $query->radio_group(-name=>'group_name',
                                 -values=>['eenie','meenie','minie','moe'],
                                 -rows=2,-columns=>2);
    

    radio_group() creates a set of logically-related radio buttons (turning one member of the group on turns the others off)

    Parameters:
  • .

    The first argument is the name of the group and is required (-name).

  • . The second argument (-values) is the list of values for the radio buttons. The values and the labels that appear on the page are identical. Pass an array reference in the second argument, either using an anonymous array, as shown, or by referencing a named array as in ``\@foo''.

  • . The optional third parameter (-default) is the name of the default button to turn on. If not specified, the first item will be the default. You can provide a nonexistent button name, such as ``-'' to start up with no buttons selected.

  • . The optional fourth parameter (-linebreak) can be set to 'true' to put line breaks between the buttons, creating a vertical list.

  • . The optional fifth parameter (-labels) is a pointer to an associative array relating the radio button values to user-visible labels to be used in the display. If not provided, the values themselves are displayed.

  • . HTML3-compatible browsers (such as Netscape) can take advantage of the optional parameters -rows, and -columns. These parameters cause radio_group() to return an HTML3 compatible table containing the radio group formatted with the specified number of rows and columns. You can provide just the -columns parameter if you wish; radio_group will calculate the correct number of rows for you.

    To include row and column headings in the returned table, you can use the -rowheader and -colheader parameters. Both of these accept a pointer to an array of headings to use. The headings are just decorative. They don't reorganize the interpetation of the radio buttons -- they're still a single named unit.

  • When the form is processed, the selected radio button can be retrieved using:

          $which_radio_button = $query->param('group_name');
    

    The value returned by radio_group() is actually an array of button elements. You can capture them and use them within tables, lists, or in other creative ways:

        @h = $query->radio_group(-name=>'group_name',-values=>\@values);
        &use_in_creative_way(@h);
    

    CREATING A SUBMIT BUTTON

       print $query->submit(-name=>'button_name',
                            -value=>'value');
    

            -or-
    

       print $query->submit('button_name','value');
    

    submit() will create the query submission button. Every form should have one of these.

    Parameters:
  • .

    The first argument (-name) is optional. You can give the button a name if you have several submission buttons in your form and you want to distinguish between them. The name will also be used as the user-visible label. Be aware that a few older browsers don't deal with this correctly and never send back a value from a button.

  • . The second argument (-value) is also optional. This gives the button a value that will be passed to your script in the query string.
  • You can figure out which button was pressed by using different values for each one:

         $which_one = $query->param('button_name');
    

    JAVASCRIPTING: radio_group() recognizes the -onClick parameter. See checkbox_group() for further details.

    CREATING A RESET BUTTON

       print $query->reset
    

    reset() creates the ``reset'' button. Note that it restores the form to its value from the last time the script was called, NOT necessarily to the defaults.

    CREATING A DEFAULT BUTTON

       print $query->defaults('button_label')
    

    defaults() creates a button that, when invoked, will cause the form to be completely reset to its defaults, wiping out all the changes the user ever made.

    CREATING A HIDDEN FIELD

            print $query->hidden(-name=>'hidden_name',
                                 -default=>['value1','value2'...]);
    

                    -or-
    

            print $query->hidden('hidden_name','value1','value2'...);
    

    hidden() produces a text field that can't be seen by the user. It is useful for passing state variable information from one invocation of the script to the next.

    Parameters:
  • .

    The first argument is required and specifies the name of this field (-name).

  • . The second argument is also required and specifies its value (-default). In the named parameter style of calling, you can provide a single value here or a reference to a whole list
  • Fetch the value of a hidden field this way:

         $hidden_value = $query->param('hidden_name');
    

    Note, that just like all the other form elements, the value of a hidden field is ``sticky''. If you want to replace a hidden field with some other values after the script has been called once you'll have to do it manually:

         $query->param('hidden_name','new','values','here');
    

    CREATING A CLICKABLE IMAGE BUTTON

         print $query->image_button(-name=>'button_name',
                                    -src=>'/source/URL',
                                    -align=>'MIDDLE');      
    

            -or-
    

         print $query->image_button('button_name','/source/URL','MIDDLE');
    

    image_button() produces a clickable image. When it's clicked on the position of the click is returned to your script as ``button_name.x'' and ``button_name.y'', where ``button_name'' is the name you've assigned to it.

    JAVASCRIPTING: image_button() recognizes the -onClick parameter. See checkbox_group() for further details.

    Parameters:
  • .

    The first argument (-name) is required and specifies the name of this field.

  • . The second argument (-src) is also required and specifies the URL
  • The third option (-align, optional) is an alignment type, and may be TOP, BOTTOM or MIDDLE
  • Fetch the value of the button this way: $x = $query->param('button_name.x'); $y = $query->param('button_name.y');

    CREATING A JAVASCRIPT ACTION BUTTON

         print $query->button(-name=>'button_name',
                              -value=>'user visible label',
                              -onClick=>"do_something()");
    

            -or-
    

         print $query->button('button_name',"do_something()");
    

    button() produces a button that is compatible with Netscape 2.0's JavaScript. When it's pressed the fragment of JavaScript code pointed to by the -onClick parameter will be executed. On non-Netscape browsers this form element will probably not even display.

    NETSCAPE COOKIES

    Netscape browsers versions 1.1 and higher support a so-called ``cookie'' designed to help maintain state within a browser session. CGI.pm has several methods that support cookies.

    A cookie is a name=value pair much like the named parameters in a CGI query string. CGI scripts create one or more cookies and send them to the browser in the HTTP header. The browser maintains a list of cookies that belong to a particular Web server, and returns them to the CGI script during subsequent interactions.

    In addition to the required name=value pair, each cookie has several optional attributes:

    1. an expiration time

      This is a time/date string (in a special GMT format) that indicates when a cookie expires. The cookie will be saved and returned to your script until this expiration date is reached if the user exits Netscape and restarts it. If an expiration date isn't specified, the cookie will remain active until the user quits Netscape.

    2. a domain This is a partial or complete domain name for which the cookie is valid. The browser will return the cookie to any host that matches the partial domain name. For example, if you specify a domain name of ``.capricorn.com'', then Netscape will return the cookie to Web servers running on any of the machines ``www.capricorn.com'', ``www2.capricorn.com'', ``feckless.capricorn.com'', etc. Domain names must contain at least two periods to prevent attempts to match on top level domains like ``.edu''. If no domain is specified, then the browser will only return the cookie to servers on the host the cookie originated from.

    3. a path If you provide a cookie path attribute, the browser will check it against your script's URL before returning the cookie. For example, if you specify the path ``/cgi-bin'', then the cookie will be returned to each of the scripts ``/cgi-bin/tally.pl'', ``/cgi-bin/order.pl'', and ``/cgi-bin/customer_service/complain.pl'', but not to the script ``/cgi-private/site_admin.pl''. By default, path is set to ``/'', which causes the cookie to be sent to any CGI script on your site.

    4. a "secure" flag If the ``secure'' attribute is set, the cookie will only be sent to your script if the CGI request is occurring on a secure channel, such as SSL.

    The interface to Netscape cookies is the cookie() method:

        $cookie = $query->cookie(-name=>'sessionID',
                                 -value=>'xyzzy',
                                 -expires=>'+1h',
                                 -path=>'/cgi-bin/database',
                                 -domain=>'.capricorn.org',
                                 -secure=>1);
        print $query->header(-cookie=>$cookie);
    

    cookie() creates a new cookie. Its parameters include:

    -name

    The name of the cookie (required). This can be any string at all. Although Netscape limits its cookie names to non-whitespace alphanumeric characters, CGI.pm removes this restriction by escaping and unescaping cookies behind the scenes.

    -value

    The value of the cookie. This can be any scalar value, array reference, or even associative array reference. For example, you can store an entire associative array into a cookie this way:

            $cookie=$query->cookie(-name=>'family information',
                                   -value=>\%childrens_ages);
    
    -path

    The optional partial path for which this cookie will be valid, as described above.

    -domain

    The optional partial domain for which this cookie will be valid, as described above.

    -expires

    The optional expiration date for this cookie. The format is as described in the section on the header() method:

            "+1h"  one hour from now
    
    -secure

    If set to true, this cookie will only be used within a secure SSL session.

    The cookie created by cookie() must be incorporated into the HTTP header within the string returned by the header() method:

            print $query->header(-cookie=>$my_cookie);
    

    To create multiple cookies, give header() an array reference:

            $cookie1 = $query->cookie(-name=>'riddle_name',
                                      -value=>"The Sphynx's Question");
            $cookie2 = $query->cookie(-name=>'answers',
                                      -value=>\%answers);
            print $query->header(-cookie=>[$cookie1,$cookie2]);
    

    To retrieve a cookie, request it by name by calling cookie() method without the -value parameter:

            use CGI;
            $query = new CGI;
            %answers = $query->cookie(-name=>'answers');
            # $query->cookie('answers') will work too!
    

    The cookie and CGI namespaces are separate. If you have a parameter named 'answers' and a cookie named 'answers', the values retrieved by param() and cookie() are independent of each other. However, it's simple to turn a CGI parameter into a cookie, and vice-versa:

       # turn a CGI parameter into a cookie
       $c=$q->cookie(-name=>'answers',-value=>[$q->param('answers')]);
       # vice-versa
       $q->param(-name=>'answers',-value=>[$q->cookie('answers')]);
    

    See the cookie.cgi example script for some ideas on how to use cookies effectively.

    NOTE: There appear to be some (undocumented) restrictions on Netscape cookies. In Netscape 2.01, at least, I haven't been able to set more than three cookies at a time. There may also be limits on the length of cookies. If you need to store a lot of information, it's probably better to create a unique session ID, store it in a cookie, and use the session ID to locate an external file/database saved on the server's side of the connection.

    WORKING WITH NETSCAPE FRAMES

    It's possible for CGI.pm scripts to write into several browser panels and windows using Netscape's frame mechanism. There are three techniques for defining new frames programmatically:

    1. Create a <Frameset> document

      After writing out the HTTP header, instead of creating a standard HTML document using the start_html() call, create a <FRAMESET> document that defines the frames on the page. Specify your script(s) (with appropriate parameters) as the SRC for each of the frames.

      There is no specific support for creating <FRAMESET> sections in CGI.pm, but the HTML is very simple to write. See the frame documentation in Netscape's home pages for details

        frames
      
    2. Specify the destination for the document in the HTTP header

      You may provide a -target parameter to the header() method: print $q->header(-target=>'ResultsWindow');

      This will tell Netscape to load the output of your script into the frame named ``ResultsWindow''. If a frame of that name doesn't already exist, Netscape will pop up a new window and load your script's document into that. There are a number of magic names that you can use for targets. See the frame documents on Netscape's home pages for details.

    3. Specify the destination for the document in the <FORM> tag You can specify the frame to load in the FORM tag itself. With CGI.pm it looks like this:

          print $q->startform(-target=>'ResultsWindow');
      

      When your script is reinvoked by the form, its output will be loaded into the frame named ``ResultsWindow''. If one doesn't already exist a new window will be created.

    The script ``frameset.cgi'' in the examples directory shows one way to create pages in which the fill-out form and the response live in side-by-side frames.

    LIMITED SUPPORT FOR CASCADING STYLE SHEETS

    CGI.pm has limited support for HTML3's cascading style sheets (css). To incorporate a stylesheet into your document, pass the start_html() method a -style parameter. The value of this parameter may be a scalar, in which case it is incorporated directly into a < STYLE> section, or it may be a hash reference. In the latter case you should provide the hash with one or more of -src or -code. -src points to a URL where an externally-defined stylesheet can be found. -code points to a scalar value to be incorporated into a < STYLE> section. Style definitions in -code override similarly-named ones in -src, hence the name ``cascading.''

    You may also specify the type of the stylesheet by adding the optional -type parameter to the hash pointed to by -style. If not specified, the style defaults to 'text/css'.

    To refer to a style within the body of your document, add the -class parameter to any HTML element:

        print h1({-class=>'Fancy'},'Welcome to the Party');
    

    Or define styles on the fly with the -style parameter:

        print h1({-style=>'Color: red;'},'Welcome to Hell');
    

    You may also use the new span() element to apply a style to a section of text:

        print span({-style=>'Color: red;'},
                   h1('Welcome to Hell'),
                   "Where did that handbasket get to?"
                   );
    

    Note that you must import the ``:html3'' definitions to have the span() method available. Here's a quick and dirty example of using CSS's. See the CSS specification at http://www.w3.org/pub/WWW/TR/Wd-css-1.html for more information.

        use CGI qw/:standard :html3/;
    

        #here's a stylesheet incorporated directly into the page
        $newStyle=<<END;
        <!-- 
        P.Tip {
            margin-right: 50pt;
            margin-left: 50pt;
            color: red;
        }
        P.Alert {
            font-size: 30pt;
            font-family: sans-serif;
          color: red;
        }
        -->
        END
        print header();
        print start_html( -title=>'CGI with Style',
                          -style=>{-src=>'http://www.capricorn.com/style/st1.css',
                                   -code=>$newStyle}
                         );
        print h1('CGI with Style'),
              p({-class=>'Tip'},
                "Better read the cascading style sheet spec before playing with this!"),
              span({-style=>'color: magenta'},
                   "Look Mom, no hands!",
                   p(),
                   "Whooo wee!"
                   );
        print end_html;
    

    DEBUGGING

    If you are running the script from the command line or in the perl debugger, you can pass the script a list of keywords or parameter=value pairs on the command line or from standard input (you don't have to worry about tricking your script into reading from environment variables). You can pass keywords like this:

        your_script.pl keyword1 keyword2 keyword3
    

    or this:

       your_script.pl keyword1+keyword2+keyword3
    

    or this:

        your_script.pl name1=value1 name2=value2
    

    or this:

        your_script.pl name1=value1&name2=value2
    

    or even as newline-delimited parameters on standard input.

    When debugging, you can use quotes and backslashes to escape characters in the familiar shell manner, letting you place spaces and other funny characters in your parameter=value pairs:

       your_script.pl "name1='I am a long value'" "name2=two\ words"
    

    DUMPING OUT ALL THE NAME/VALUE PAIRS

    The dump() method produces a string consisting of all the query's name/value pairs formatted nicely as a nested list. This is useful for debugging purposes:

        print $query->dump
        
    

    Produces something that looks like:

        <UL>
        <LI>name1
            <UL>
            <LI>value1
            <LI>value2
            </UL>
        <LI>name2
            <UL>
            <LI>value1
            </UL>
        </UL>
    

    You can pass a value of 'true' to dump() in order to get it to print the results out as plain text, suitable for incorporating into a <PRE> section.

    As a shortcut, as of version 1.56 you can interpolate the entire CGI object into a string and it will be replaced with the a nice HTML dump shown above:

        $query=new CGI;
        print "<H2>Current Values</H2> $query\n";
    

    FETCHING ENVIRONMENT VARIABLES

    Some of the more useful environment variables can be fetched through this interface. The methods are as follows:

    accept()

    Return a list of MIME types that the remote browser accepts. If you give this method a single argument corresponding to a MIME type, as in $query->accept('text/html'), it will return a floating point value corresponding to the browser's preference for this type from 0.0 (don't want) to 1.0. Glob types (e.g. text/*) in the browser's accept list are handled correctly.

    raw_cookie()

    Returns the HTTP_COOKIE variable, an HTTP extension implemented by Netscape browsers version 1.1 and higher. Cookies have a special format, and this method call just returns the raw form (?cookie dough). See cookie() for ways of setting and retrieving cooked cookies.

    Called with no parameters, raw_cookie() returns the packed cookie structure. You can separate it into individual cookies by splitting on the character sequence ``; ''. Called with the name of a cookie, retrieves the unescaped form of the cookie. You can use the regular cookie() method to get the names, or use the raw_fetch() method from the CGI::Cookie module.

    user_agent()

    Returns the HTTP_USER_AGENT variable. If you give this method a single argument, it will attempt to pattern match on it, allowing you to do something like $query->user_agent(netscape);

    path_info()

    Returns additional path information from the script URL. E.G. fetching /cgi-bin/your_script/additional/stuff will result in $query->path_info() returning ``additional/stuff''.

    NOTE: The Microsoft Internet Information Server is broken with respect to additional path information. If you use the Perl DLL library, the IIS server will attempt to execute the additional path information as a Perl script. If you use the ordinary file associations mapping, the path information will be present in the environment, but incorrect. The best thing to do is to avoid using additional path information in CGI scripts destined for use with IIS.

    path_translated()

    As per path_info() but returns the additional path information translated into a physical path, e.g. ``/usr/local/etc/httpd/htdocs/additional/stuff''.

    The Microsoft IIS is broken with respect to the translated path as well.

    remote_host()

    Returns either the remote host name or IP address. if the former is unavailable.

    script_name() Return the script name as a partial URL, for self-refering scripts.
    referer()

    Return the URL of the page the browser was viewing prior to fetching your script. Not available for all browsers.

    auth_type ()

    Return the authorization/verification method in use for this script, if any.

    server_name ()

    Returns the name of the server, usually the machine's host name.

    virtual_host ()

    When using virtual hosts, returns the name of the host that the browser attempted to contact

    server_software ()

    Returns the server software and version number.

    remote_user ()

    Return the authorization/verification name used for user verification, if this script is protected.

    user_name ()

    Attempt to obtain the remote user's name, using a variety of different techniques. This only works with older browsers such as Mosaic. Netscape does not reliably report the user name!

    request_method()

    Returns the method used to access your script, usually one of 'POST', 'GET' or 'HEAD'.

    USING NPH SCRIPTS

    NPH, or ``no-parsed-header'', scripts bypass the server completely by sending the complete HTTP header directly to the browser. This has slight performance benefits, but is of most use for taking advantage of HTTP extensions that are not directly supported by your server, such as server push and PICS headers.

    Servers use a variety of conventions for designating CGI scripts as NPH. Many Unix servers look at the beginning of the script's name for the prefix ``nph-''. The Macintosh WebSTAR server and Microsoft's Internet Information Server, in contrast, try to decide whether a program is an NPH script by examining the first line of script output.

    CGI.pm supports NPH scripts with a special NPH mode. When in this mode, CGI.pm will output the necessary extra header information when the header() and redirect() methods are called.

    The Microsoft Internet Information Server requires NPH mode. As of version 2.30, CGI.pm will automatically detect when the script is running under IIS and put itself into this mode. You do not need to do this manually, although it won't hurt anything if you do.

    There are a number of ways to put CGI.pm into NPH mode:

    In the use statement

    Simply add the ``-nph'' pragmato the list of symbols to be imported into your script:

          use CGI qw(:standard -nph)
    
    By calling the nph() method:

    Call nph() with a non-zero parameter at any point after using CGI.pm in your program.

          CGI->nph(1)
    
    By using -nph parameters in the header() and redirect() statements:

          print $q->header(-nph=>1);
    

    Server Push

    CGI.pm provides three simple functions for producing multipart documents of the type needed to implement server push. These functions were graciously provided by Ed Jordan <ed@fidalgo.net> To import these into your namespace, you must import the ``:push'' set. You are also advised to put the script into NPH mode and to set $| to 1 to avoid buffering problems.

    Here is a simple script that demonstrates server push:

      #!/usr/local/bin/perl
      use CGI qw/:push -nph/;
      $| = 1;
      print multipart_init(-boundary=>'----------------here we go!');
      while (1) {
          print multipart_start(-type=>'text/plain'),
                "The current time is ",scalar(localtime),"\n",
                multipart_end;
          sleep 1;
      }
    

    This script initializes server push by calling multipart_init(). It then enters an infinite loop in which it begins a new multipart section by calling multipart_start(), prints the current local time, and ends a multipart section with multipart_end(). It then sleeps a second, and begins again.

    multipart_init() multipart_init(-boundary=>$boundary);

    Initialize the multipart system. The -boundary argument specifies what MIME boundary string to use to separate parts of the document. If not provided, CGI.pm chooses a reasonable boundary for you.

    multipart_start()

      multipart_start(-type=>$type)
    

    Start a new part of the multipart document using the specified MIME type. If not specified, text/html is assumed.

    multipart_end()

      multipart_end()
    

    End a part. You must remember to call multipart_end() once for each multipart_start().

    Users interested in server push applications should also have a look at the CGI::Push module.

    Avoiding Denial of Service Attacks

    A potential problem with CGI.pm is that, by default, it attempts to process form POSTings no matter how large they are. A wily hacker could attack your site by sending a CGI script a huge POST of many megabytes. CGI.pm will attempt to read the entire POST into a variable, growing hugely in size until it runs out of memory. While the script attempts to allocate the memory the system may slow down dramatically. This is a form of denial of service attack.

    Another possible attack is for the remote user to force CGI.pm to accept a huge file upload. CGI.pm will accept the upload and store it in a temporary directory even if your script doesn't expect to receive an uploaded file. CGI.pm will delete the file automatically when it terminates, but in the meantime the remote user may have filled up the server's disk space, causing problems for other programs.

    The best way to avoid denial of service attacks is to limit the amount of memory, CPU time and disk space that CGI scripts can use. Some Web servers come with built-in facilities to accomplish this. In other cases, you can use the shell limit or ulimit commands to put ceilings on CGI resource usage.

    CGI.pm also has some simple built-in protections against denial of service attacks, but you must activate them before you can use them. These take the form of two global variables in the CGI name space:

    $CGI::POST_MAX

    If set to a non-negative integer, this variable puts a ceiling on the size of POSTings, in bytes. If CGI.pm detects a POST that is greater than the ceiling, it will immediately exit with an error message. This value will affect both ordinary POSTs and multipart POSTs, meaning that it limits the maximum size of file uploads as well. You should set this to a reasonably high value, such as 1 megabyte.

    $CGI::DISABLE_UPLOADS

    If set to a non-zero value, this will disable file uploads completely. Other fill-out form values will work as usual.

    You can use these variables in either of two ways.

    1. On a script-by-script basis

      Set the variable at the top of the script, right after the ``use'' statement:

          use CGI qw/:standard/;
          use CGI::Carp 'fatalsToBrowser';
          $CGI::POST_MAX=1024 * 100;  # max 100K posts
          $CGI::DISABLE_UPLOADS = 1;  # no uploads
      
    2. Globally for all scripts

      Open up CGI.pm, find the definitions for $POST_MAX and $DISABLE_UPLOADS, and set them to the desired values. You'll find them towards the top of the file in a subroutine named initialize_globals().

    Since an attempt to send a POST larger than $POST_MAX bytes will cause a fatal error, you might want to use CGI::Carp to echo the fatal error message to the browser window as shown in the example above. Otherwise the remote user will see only a generic ``Internal Server'' error message. See the CGI::Carp manual page for more details.

    COMPATIBILITY WITH CGI-LIB.PL

    To make it easier to port existing programs that use cgi-lib.pl the compatibility routine ``ReadParse'' is provided. Porting is simple:

    OLD VERSION require ``cgi-lib.pl''; &ReadParse; print ``The value of the antique is $in{antique}.\n'';

    NEW VERSION use CGI; CGI::ReadParse print ``The value of the antique is $in{antique}.\n'';

    CGI.pm's ReadParse() routine creates a tied variable named %in, which can be accessed to obtain the query variables. Like ReadParse, you can also provide your own variable. Infrequently used features of ReadParse, such as the creation of @in and $in variables, are not supported.

    Once you use ReadParse, you can retrieve the query object itself this way:

        $q = $in{CGI};
        print $q->textfield(-name=>'wow',
                            -value=>'does this really work?');
    

    This allows you to start using the more interesting features of CGI.pm without rewriting your old scripts from scratch.

    AUTHOR INFORMATION

    Copyright 1995-1997, Lincoln D. Stein. All rights reserved. It may be used and modified freely, but I do request that this copyright notice remain attached to the file. You may modify this module as you wish, but if you redistribute a modified version, please attach a note listing the modifications you have made.

    Address bug reports and comments to: lstein@genome.wi.mit.edu

    CREDITS

    Thanks very much to:

    Matt Heffron (heffron@falstaff.css.beckman.com)
    James Taylor (james.taylor@srs.gov)
    Scott Anguish <sanguish@digifix.com>
    Mike Jewell (mlj3u@virginia.edu)
    Timothy Shimmin (tes@kbs.citri.edu.au)
    Joergen Haegg (jh@axis.se)
    Laurent Delfosse (delfosse@csgrad1.cs.wvu.edu)
    Richard Resnick (applepi1@aol.com)
    Craig Bishop (csb@barwonwater.vic.gov.au)
    Tony Curtis (tc@vcpc.univie.ac.at)
    Tim Bunce (Tim.Bunce@ig.co.uk)
    Tom Christiansen (tchrist@convex.com)
    Andreas Koenig (k@franz.ww.TU-Berlin.DE)
    Tim MacKenzie (Tim.MacKenzie@fulcrum.com.au)
    Kevin B. Hendricks (kbhend@dogwood.tyler.wm.edu)
    Stephen Dahmen (joyfire@inxpress.net)
    Ed Jordan (ed@fidalgo.net)
    David Alan Pisoni (david@cnation.com)
    Doug MacEachern (dougm@opengroup.org)
    Robin Houston (robin@oneworld.org)
    ...and many many more...

    for suggestions and bug fixes.

    A COMPLETE EXAMPLE OF A SIMPLE FORM-BASED SCRIPT

            #!/usr/local/bin/perl
         
            use CGI;
     
            $query = new CGI;
    

            print $query->header;
            print $query->start_html("Example CGI.pm Form");
            print "<H1> Example CGI.pm Form</H1>\n";
            &print_prompt($query);
            &do_work($query);
            &print_tail;
            print $query->end_html;
     
            sub print_prompt {
               my($query) = @_;
     
               print $query->startform;
               print "<EM>What's your name?</EM><BR>";
               print $query->textfield('name');
               print $query->checkbox('Not my real name');
     
               print "<P><EM>Where can you find English Sparrows?</EM><BR>";
               print $query->checkbox_group(
                                     -name=>'Sparrow locations',
                                     -values=>[England,France,Spain,Asia,Hoboken],
                                     -linebreak=>'yes',
                                     -defaults=>[England,Asia]);
     
               print "<P><EM>How far can they fly?</EM><BR>",
                    $query->radio_group(
                            -name=>'how far',
                            -values=>['10 ft','1 mile','10 miles','real far'],
                            -default=>'1 mile');
     
               print "<P><EM>What's your favorite color?</EM>  ";
               print $query->popup_menu(-name=>'Color',
                                        -values=>['black','brown','red','yellow'],
                                        -default=>'red');
     
               print $query->hidden('Reference','Monty Python and the Holy Grail');
     
               print "<P><EM>What have you got there?</EM><BR>";
               print $query->scrolling_list(
                             -name=>'possessions',
                             -values=>['A Coconut','A Grail','An Icon',
                                       'A Sword','A Ticket'],
                             -size=>5,
                             -multiple=>'true');
     
               print "<P><EM>Any parting comments?</EM><BR>";
               print $query->textarea(-name=>'Comments',
                                      -rows=>10,
                                      -columns=>50);
     
               print "<P>",$query->reset;
               print $query->submit('Action','Shout');
               print $query->submit('Action','Scream');
               print $query->endform;
               print "<HR>\n";
            }
     
            sub do_work {
               my($query) = @_;
               my(@values,$key);
    

               print "<H2>Here are the current settings in this form</H2>";
    

               foreach $key ($query->param) {
                  print "<STRONG>$key</STRONG> -> ";
                  @values = $query->param($key);
                  print join(", ",@values),"<BR>\n";
              }
            }
     
            sub print_tail {
               print <<END;
            <HR>
            <ADDRESS>Lincoln D. Stein</ADDRESS><BR>
            <A HREF="/">Home Page</A>
            END
            }
    

    BUGS

    This module has grown large and monolithic. Furthermore it's doing many things, such as handling URLs, parsing CGI input, writing HTML, etc., that are also done in the LWP modules. It should be discarded in favor of the CGI::* modules, but somehow I continue to work on it.

    Note that the code is truly contorted in order to avoid spurious warnings when programs are run with the -w switch.

    SEE ALSO

    CGI::Carp, URI, CGI::Request, CGI::MiniSvr, CGI::Base, CGI::Form, CGI::Apache, CGI::Switch, CGI::Push, CGI::Fast


    DISCLAIMER

    We are painfully aware that these documents may contain incorrect links and misformatted HTML. Such bugs lie in the automatic translation process that automatically created the hundreds and hundreds of separate documents that you find here. Please do not report link or formatting bugs, because we cannot fix per-document problems. The only bug reports that will help us are those that supply working patches to the installhtml or pod2html programs, or to the Pod::HTML module itself, for which I and the entire Perl community will shower you with thanks and praises.

    If rather than formatting bugs, you encounter substantive content errors in these documents, such as mistakes in the explanations or code, please use the perlbug utility included with the Perl distribution.

    --Tom Christiansen, Perl Documentation Compiler and Editor


    Return to the index.
    Return to the Perl Home Page. </BODY> </HTML>