ACGI program receives three types of information from the server:
We look at each of these in turn . 7.7.1 Request InformationThe webserver makes available to the CGI script information about the current request called session information . This information can be retrieved with several provided methods . Client information consists of the following:
The first four items are straightforward. The two functions path_info() and query_string() are a bit more involved, and they are discussed in detail in Sections 7.7.2 and 7.7.3. Server information consists of:
We can show the use of many of these methods in a single example: #! /usr/bin/perl # info4.cgi use CGI :standard; print header(), start_html(More System Information), h1(Client Information), Here is some information about the client:, ul(li(The remote host: , remote_host()), li(The user agent: , user_agent()), li(The referer: , referer())), h1(Server Information), Here is some information about the server:, ul(li(The server name: , server_name()), li(The server software: , server_software()), li(The server port: , server_port()), li(The script name: , script_name())), end_html(); The result of this program can be seen in Figure 7.8. Figure 7.8. More CGI information
The example uses two methods to generate HTML lists, ul() and li() . The ul() method generates <UL> ... </UL> and the li() method generates <LI> ... </LI> . The methods nest, so the result of the CGI.pm method is the same as: <UL><LI>The remote host: www.opensourcewebbook.com</LI> <LI>The user...</LI></UL> 7.7.2 Path InformationThe path information is text that is passed into the CGI program if it exists in the URL after the CGI program name and before the question mark (we talk about the question mark next , when we discuss processing posted form data). This data can be used for a variety of reasons: as information about a path, data that causes the CGI program to perform in a specific manner, or just about anything that you need. For instance, let's say we are writing a messaging system allowing the user to post to and read from message boards. There are a number of boards and in each board a number of messages. We could pass the board that the user is browsing and the message they are reading in through the path information, as in this URL: http://www.example.com/cgi-bin/messageboard/webprogramming/19312 In this example, the name of the program is messageboard (yes, it could be named messageboard.cgi , but this is a matter of preference), the board the user is browsing is webprogramming , and the message is number 19312 (perhaps a message about this book?). So the path information can be just about any information that you choose to pass in to the CGI program. The path information can be obtained either from %ENV , the hash that contains the CGI program's environment: $env_path = $ENV{PATH_INFO} ; or by using the CGI method path_info() : $method_path = path_info() ; Here's an example of a CGI program that displays the path information using both %ENV and path_info() . Place this code in the file /var/www/cgi-bin/path_info.cgi : #! /usr/bin/perl # path_info.cgi use strict; use CGI :standard; #get the path from %ENV, then from the # CGI method path_info() my $env_path = $ENV{PATH_INFO} ; my $method_path = path_info() ; print header, start_html(-title => Path Information, -bgcolor => #ffffff), From %ENV: , b($env_path), br(), From path_info(): , b($method_path), end_html(); As an example, load one of these URLs in your browser: http://localhost/cgi-bin/path_info.cgi/foo/bar or www.opensourcewebbook.com/cgi-bin/path_info.cgi/foo/bar. Notice that the text " /foo/bar " that follows the CGI program name is the path information. Proof of this can be seen in Figure 7.9. Figure 7.9. CGI path information
7.7.3 Processing Posted Form DataWere you wondering when we were going to talk about the mysterious query string? That time has come. The third class of information that the CGI script receives is posted form data (if any). An example is data that comes from an HTML form that has as its action the CGI program in question. Here is a form example stored in /var/www/html/cgi/nameage.html : <html> <head> <title>Enter Your Name and Age</title> </head> <body bgcolor="#ffffff"> <form action="/cgi-bin/nameage.cgi" method="get"> Name: <input type="text" name="yourname"> <br> Age: <input type="text" name="age"> <br> <input type="submit" value="Click to Submit"> </form> </body> </html> This program results in a web page like that shown in Figure 7.10. Figure 7.10. Enter name and age
When the user clicks the Click to Submit button, the program given as the action ”in this case /cgi-bin/nameage.cgi , which corresponds to the executable program /var/www/cgi-bin/nameage.cgi ”is executed. Posted data is sent to the program ”here the posted data is the name of the fields ( yourname and age ) and the values entered into those fields. Notice that when the data is sent to the program, the URL resembles this: http://localhost/cgi-bin/nameage.cgi?yourname=J.+Random+Luser&age=55 The program's name is followed by a question mark ( ? ). The question mark is then followed by this funny looking text: yourname=J.+Random+Luser&age=55 This data is called URL encoded data and is passed into the CGI program through the query string . It is the data from the form that is encoded into a format that can be sent to the webserver through the URL.
The query string format is a collection of form widget name/value pairs separated by the equal sign ( = ), each pair separated from the next by an ampersand ( & ). So in the example, there are two name/value pairs: yourname=J.+Random+Luser age=55 The text that is posted may contain text that is not legal in a URL (such as a space). This text is encoded before being sent to the server. Spaces are replaced with the plus sign ( + ), as shown in the example, and other disallowed characters are replaced with a percent character followed by the hexadecimal representation of that character's ASCII value. For instance, the exclamation point character ( ! ) is replaced with %21 . The URL contains the posted data following the " ? " because the form was created with method="GET" . The GET method passes the data through the URL in the query string. The alternative is to use method="POST" . This method passes the data to the CGI program through its standard input instead of through the URL. Either way, CGI.pm handles the data passed in. These are the contents of nameage.cgi : #!/usr/bin/perl # nameage.cgi use strict; use CGI :standard; my $name = param(yourname) John Doe; my $age = param(age) 0; my @params = param(); print header(), start_html(Your Name and Age), "Hello $name, you are $age years old.", hr(), The parameters entered are: , b("@params"), end_html(); The most important method shown in this example is the param() method. This method works either with or without an argument. If param() is called with an argument: $name = param(yourname) John Doe; it returns the value posted for that form widget. Note that the name of the form text widget for the name is " yourname ". Passed with that name is the value that the user enters. Executing param( yourname ) returns the value entered by the user into the form, or the empty string if the user does not enter any text into that widget. Recall from Chapter 4 that the " logical or " operator used in this statement, , is really shorthand for this logic: if (param(yourname)ne) { $name = param(yourname); } else { $name = John Doe; } This makes sure that $name is valid no matter what the user enters, defaulting to " John Doe " if the user doesn't enter a value. If param() is called with no arguments: @params = param(); it returns a list of all the widget names in the form ” yourname , age . If the user entered the name J. Random Luser and the age 55 into the form, the result of nameage.cgi would look like Figure 7.11. Figure 7.11. Name and age results
Let's examine a more complicated example showing many more form widgets. The example in /var/www/html/cgi/widgets.html can be found online at http://localhost/cgi/widgets.html.txt or www.opensourcewebbook.com/cgi/widgets.html.txt. It creates the form shown in Figure 7.12. Figure 7.12. Widget examples
After the beginning HTML, we see the creation of the form: <form action="/cgi-bin/widgets.cgi" method="post"> This means that when this form is submitted, all the data in the form are sent to the program widgets.cgi . Then a bunch of widgets are created. A text widget, or a one-line box in which the user can enter text: Programming language: <input type="text" name="language" value="Perl"> A text widget, or a multiline area in which the user can enter lines of text: Comments: <br> <textarea name="comments" cols="20" rows="5"></textarea> A radio button group allowing the user to select one-of-many choices: Rate the coolness: <input type="radio" name="coolness" value="cool"> cool <input type="radio" name="coolness" value="very cool"> very cool <input type="radio" name="coolness" value="ice cold" checked> ice cold A check box, or an on-or-off selection: I will learn more about Perl and CGI: <input type="checkbox" name="learnmore" value="yes" checked> Yes Two menus are defined with the <select> tag. I will use this operating system: <select name="operating_system" size="1"> <option>Linux</option> <option>Solaris</option> <option>HPUX</option> </select> <br> My favorite animal(s): <select name="animal" size="3" multiple> <option>Penguin</option> <option>Camel</option> <option>Llama</option> <option>Panther</option> </select> The first is a menu button that is clicked, and then the item desired is selected. This is a menu button because the size is set to 1, so only one item is shown in the GUI until the widget is clicked. The other <select> widget is a scrolling list box ”since the size is 3, three selections are shown in the box, and the others are viewable by scrolling (hmmm, scrolling list box...that's a good name for this widget). Note that the attribute multiple is indicated, which means the user can select more than one option by control-clicking the additional items. The fact that more than one item can be selected becomes important when the values selected are grabbed. The submit and reset buttons are created: <input type="submit" value="Submit Form"> <input type="reset" value="Reset Form"> If the submit button is clicked, the data is sent to the program widgets.cgi . If the reset button is clicked, the form is reset to its original values. The associated CGI script to process the posted data is in the file /var/www/cgi-bin/widgets.cgi . You can find this file at http://localhost/cgi/widgets.cgi or www.opensourcewebbook.com/cgi/widgets.cgi. First we see something important: #! /usr/bin/perl # widgets.cgi use strict; use CGI :standard; It is a Perl script. Yes! Also, we are using the CGI.pm module in the standard mode, as we have done before. Then we see the code to grab the posted data: # get the posted form data my $language = param(language) Perl; my $comments = param(comments) ; my $coolness = param(coolness) Ice Cold; my $learnmore = param(learnmore) no; my $operating_system = param(operating system) Linux; # use an array here since we can choose more than one animal my @animal = param(animal); Note how each variable that is being assigned posted data has an appropriate default value. Also, because more than one animal can be selected (remember, the <select> widget had the multiple attribute set, so the user can select more than one animal), the param() function is assigned to an array ”CGI.pm returns all the items selected as a list, here assigned to @animal . Then we see the code to print the content: print header(), start_html(-title => Process Widgets, -bgcolor => #ffffff), h1(Process widgets), You entered the following information into the form:, br(), Language: , b($language), br(), Comments:, br(), b($comments), br(), Coolness level: , b($coolness), br(), You want to learn more about Perl and CGI: , b($learnmore), br(), Your operating system of choice is: , b($operating_system), br(), Your favorite animal(s) is/are: , b("@animal"), end_html; This looks like the code we have seen before. A sample result is shown in Figure 7.13. Figure 7.13. Widget example result
This works well enough, but there is a drawback. There are two files to maintain: widgets.html and widgets.cgi . Wouldn't it be nice to simply have one file that we need to maintain? This is possible if we write the CGI program more generally to have two distinct functions.
This can be done by modifying widgets.cgi with an if statement, as shown in /var/www/cgi-bin/widgets2.cgi . You can view it in its entirety at http://localhost/cgi/widgets2.cgi or www.opensourcewebbook.com/cgi/widgets2.cgi. A quick look at the overall program shows that it is one big if ... else : if (param) { # we have posted parameters, so process them } else { # no posted data, so build the form } The if portion of widgets2.cgi resembles the previous example, widgets.cgi : if (param) { # we are here if there was any data posted, so process it # get the posted form data my $language = param(language) Perl; my $comments = param(comments) ; my $coolness = param(coolness) Ice Cold; my $learnmore = param(learnmore) no; my $operating_system = param(operating system) Linux; # use an array here since we can choose more than one animal my @animal = param(animal); print header(), start_html(-title => Process Widgets, -bgcolor => #ffffff), h1(Process widgets), You entered the following information into the form:, br(), Language: , b($language), br(), Comments:, br(), b($comments), br(), Coolness level: , b($coolness), br(), You want to learn more about Perl and CGI: , b($learnmore), br(), Your operating system of choice is: , b($operating_system), br(), Your favorite animal(s) is/are: , b("@animal"), end_html; The else part, executed if no parameters are posted, is one big here document (after the header() is printed). The nice thing about the here document is that the HTML printed is more or less exactly the same as we saw in widgets.html (we won't show all of it): }else{ # if we are here, then we need to build the form # so print the header, then the html print header(), <<EOHTML; <html> <head> <title>An Example of Form Widgets</title> </head> <body bgcolor="#ffffff"> <h1>An Example of Form Widgets</h1> <form action="/cgi-bin/widgets2.cgi" method="post"> Programming language: <input type="text" name="language" value="Perl"> <br> . . . </form> </body> </html> EOHTML } You can try it out at this book's web site or on your own server by going to http://localhost/cgi-bin/widgets2.cgi or www.opensourcewebbook.com/cgi-bin/widgets2.cgi. |