Chapter 16. CGI and Perl

CONTENTS

CONTENTS>>

  •  Scripting with Perl
  •  A Brief Perl Tutorial
  •  Perl Operators
  •  Perl Statements
  •  File Handling in Perl
  •  Passing Data to CGI from HTML
  •  Summary

Like other server-side languages, the Practical Extraction and Report Language (Perl) is associated with a protocol, the Common Gateway Interface (CGI). Other languages are used with CGI as well but, just as VBScript is the main language associated with Active Server Pages (discussed in the previous chapter), Perl is the main language associated with CGI.

While direct scripting can occur between a UNIX (or Linux) server and your computer, the material presented in this chapter assumes that most readers want to know how to create scripts with a Windows or Macintosh OS, and not Telnet or work from a UNIX shell. So, the focus will be on writing Perl scripts and examining how they interface with JavaScript and HTML pages. The major scripting tool (if you can call it that) will be the humble text editor.

Scripting with Perl

Like all scripting languages, Perl has a set of statements, variables, functions, operators, and other typical language features. However, because Perl was designed to work with data to be passed between clients and servers, it has special commands for handling data to be stored and retrieved from the server. Variables in HTML forms can be passed to a Perl script, and JavaScript's main role lies in preprocessing the variables in the forms.

Getting Started

You will need a hosting service that provides you with access to CGI and a Perl interpreter. The examples used for this book were done using JTLNet as a hosting service (www.jtlnet.com), and you will find them to have everything you need for simple access for CGI. If you already have a hosting service, it should be capable of showing you how to set up and use CGI. If your service does not allow CGI, get another hosting service that does. You can find plenty of high-quality services for less than $8 per month.

When you get squared away with a hosting service, you will need to know where to store your CGI scripts written in Perl. Usually, the name of the folder (directory) where you put your scripts is cgi-bin. Use your favorite FTP program to place your Perl scripts in the cgi-bin directory using ASCII (not binary) transfer. You will find it in the root HTML directory, which is usually named something like public_html. The path to your Perl scripts, which end with the extension .pl, would be as follows:

http://www.domain.com/cgi-bin/scriptName.pl

The directory public_html (or whatever the root HTML directory is called) is not named in the path because it is the root for your domain for HTML.

chmod

Unlike PHP or ASP pages, CGI scripts need to be configured when they are on the server in the cgi-bin folder. The UNIX command chmod changes the permission for each Perl file that you want to execute. (In other words, all your Perl files need to be configured.) Within a UNIX shell, the command to configure your script is this:

chmod 755 scriptName.pl

If you're using a typical Windows or Macintosh OS computer, you will need another way to set the permissions. You need an FTP application that can issue a chmod command or set the permission parameters in some other way. Both PCs and Macs have plenty of FTP programs that will do that. A popular FTP program for Windows is called CuteFTP (www.cuteftp.com), and it has its own chmod command built into a drop-down menu. You simply select the file that is on the server that you want to configure and select Commands, File Actions, CHMOD; then enter the 755 code in the Manual window. On the Mac side, the popular Fetch FTP program has a permissions option that you can set without having to write the chmod command. Selecting Remote, Set Permissions, you select all of the permission options except Group and Everyone Write. Figure 16.1 shows how it looks when completed for the 755 chmod setting.

Figure 16.1. You can click the permission options to the equivalent of a chmod command with some FTP applications.

graphics/16fig01.gif

A Quick Script

To get a quick overview of a running CGI script written in Perl, the following set of steps takes you through the sequence that you will need to get a working script:

  1. Open up your favorite text editor. For the purposes of this book and most Perl applications with CGI pages, you begin all Perl scripts with this:

    #!/usr/bin/perl
  2. Because you will be writing Perl scripts in pages that will generally go to the web, you will need another generic line of code:

    print "Content-type:text/html\n\n";

    The line does not print to the screen, but it will make the rest of the code do so.

  3. Next, for output, you use a print statement to send a message to the screen. Just as in JavaScript, lines terminate with a semicolon, except that in Perl ending semicolons are not optional. You have to include them. (The \n simply puts a new line in the source of the HTML file.)

    print "I like JavaScript and Perl.\n";
  4. Tell the parser that you've reached the end using the exit statement.

    exit;
  5. At this point, the script is done and should look like the following:

    #!/usr/bin/perl  print "Content-type:text/html\n\n";  print "I like JavaScript and Perl.\n";  exit; 

    Save it as perlOne.pl.

  6. Using an FTP program, place perlOne.pl in your cgi-bin directory (or your hosting service's equivalent).

  7. When it is in the cgi-bin folder, select the file and, using the chmod command or permission matrix, configure the file to chmod 755.

  8. Open your browser and, in the URL window, type in the following, substituting your own domain name:

    http://www.domain.com/cgi-bin/perlOne.pl

    On the screen, you should see

    I like JavaScript and Perl

Other than having to initialize the script using chmod and adding the line for web pages, the process is not unlike loading a JavaScript file onto a server.

A Brief Perl Tutorial

JavaScript and Perl have some common features in terms of general structure, but Perl is unique and very powerful. One of the more powerful structures within Perl is a pattern-matching feature called regular expressions. JavaScript, too, has regular expressions; by comparing the two, you can learn about both. However, before getting to regular expressions, a quick overview of Perl is in order.

Unique Variable Characters of Perl

Perl distinguishes between different types of variables using a set of symbols with their own names. They include the following:

  • $ Scalar: a single number or string

  • @ Array: a multiple-item variable

  • % Hash: a paired array

A scalar is similar to a plain-vanilla variable in JavaScript.

Scalar Variables

The scalar variables in Perl look a lot like variables in PHP because they begin with a dollar sign. In Perl, they are simply variables with a single value. (In some versions of Basic, all string variables begin with dollar signs, but both strings and nonstrings can be Perl scalar variables.) The following are examples of scalar variables note that they include strings and numbers:

$subtotal = 22.33;  $membership=453;  $customer="Linda Sheppard"; 

One of the advantages of having identifying characters at the beginning of variables in Perl is that they can be put inside a literal without any special set of quotes or concatenation.

$meetingTotal=64;  $report="The meeting was attended by $meetingTotal last week."; 

The advantage of not having to fiddle around with concatenation turns into a disadvantage when you are faced with having to use one of the variable characters such as the dollar sign ($). As in JavaScript, the dollar sign can be "escaped" by using a backslash. For example, the following variable assignment uses an escaped dollar sign:

$total="\$23.33";  print $total; 

The output would be $23.33.

Arrays and Hashes

An array in Perl can be remembered by the @ symbol ("at" sign for "array" get it?). An array is declared by typing in the array name followed by the list of array elements in parentheses. For example, the following array contains several types of dogs:

@dogs = ("lab","sheltie","Swissy","mutt"); 

If you wanted to print out Swissy, you would enter this:

print $dogs[2]; 

At first glance, the print command looks like a typo, but it's not. In Perl, you use a scalar variable to access the elements of an array. All of the elements must be stated as follows:

$arrayName[n]; 

Because Perl variables are conceived of as singularities or pluralities, it makes sense to reference single elements of an array using the array name but a scalar symbol.

A unique variable format in Perl is the hash. Hashes are paired elements in an array or associative arrays. Hashes have two formats. The first format looks like an array, but the second is clearly descriptive:

%dogs = ("lab", "Labrador Retriever", "Berner", "Bernese Mountain Dog", "Swissy",  "Greater Swiss Mountain Dog"); 

The first element is associated with the second, the third with the fourth, and so on. A clearer way of presenting the same hash follows:

%dogs= ( "lab" => "Labrador Retriever",  "Berner"=> "Bernese Mountain Dog",  "Swissy"=> "Greater Swiss Mountain Dog",  ); 

When you have your data in a hash, how do you get it out? By referencing the first of an associative pair, you get the second of the two. The format is

$hashName{"FirstElementOfPair"}; 

Your return is the second element in a hash pair. For example, using the dog example hash, if you typed this:

print $dogs{"Berner"}; 

your screen would show

Bernese Mountain Dog

Using the hash structure is handy when you have associative pairs and can reference one for the other.

Perl Comments

Comments in Perl are prefaced by pound signs (#). As in JavaScript, comments can be put on separate lines or in lines with other code. The following examples show how they can be used:

$alpha="News"; #This is a scalar variable.  @happy=("glad", "exuberant", "cheerful", "blithe"); #Synonyms for happy;  #All comments are ignored by parser. 

Perl Operators

Perl operators, for the most part, are identical to those in JavaScript, with some notable exceptions. First, numeric and string comparison operators are different. This difference can be very frustrating after using JavaScript because it's easy to forget and use the wrong one. For example, the following script shows the correct way to use numeric and string operators:

$alpha="Apples";  $omega="Oranges";  if($alpha ne $omega) { #Uses a string comparison        print "They are different \n\n";        } 

The common error in Perl occurs when the programmer uses a line like this when both scalar variables are strings:

if($alpha != $omega) { #Wrong! 

So, when you write conditional statements in Perl, which are the same as in JavaScript, watch out for mixing string and numeric comparison operators. Table 16.1 shows the main operators in Perl. (File test operators are not included.)

Table 16.1. String and Numeric Operators in Perl

Operator

Use

Format Example

=

Assignment

$inven =832;

+

Add

$total = $item + $tax + $shipping;

-

Subtract

$discount = $regPrice - $salePrice

*

Multiply

$itemTotal = $item * $units;

/

Divide

$distrib = $all / $part;

==

Compare evaluation

if ($quarter1 == $quarter2)

!=

Not equal to

if (999 != $little) {

>

Greater than

if ($elephant > $mouse) {

<

Less than

if ($subTotal < 85) {

>=

Greater than or equal to

if ($counter >= 200) {

<=

Less than or equal to

if (300 <= $fullAmount) {

<=>

Comparison

$alpha=($beta <=> $delta);

eq

String compare evaluation

if ($Bob eq $Ben) {

ne

String not equal to

if ($big ne $little) {

lt

String less than

if ($art lt $science) {

gt

String greater than

if ("Big" gt "Tiny") {

le

String less than or equal to

if ("Apes" lt "Zebras") {

ge

String greater than or equal to

If ($first ge "Last") {

cmp

String comparison

$beta="dogs" cmp "cats";

+=

Compound assign add

$total += 21;

-=

Compound assign subtract

$discount -= (.20 * $item);

.

Concatenation

$wholeName = $firstName.$lastName;

.=

Compound concatenation

$areaCode .= $phone

&&

Logical AND

if ($first == 97 && $second <= $third) {

||

Logical OR

if ($high === 22 || $low == 12){

++

Increment (pre or post)

for ($la=6; $la <=78; ++$la)

--

Decrement (pre or post)

for ($ls=50; $ls >=12; $ls--)

Perl Statements

This brief section covers the main Perl statements and structures that you will use in a typical CGI page. Most of the statements work the same as they do in JavaScript, but the variables must be prefaced with the correct symbols, and some of the formats might be slightly different.

Output

As you have seen in examples in this chapter, the print statement seems to be the most common output statement. It is. Three key types of print statements will help you get started in Perl with CGI:

  • Print literal: print "Hamster \n\n";

  • Print variable: print $bigshot;

  • Print HTML: print "<strong> Tough </strong>";

A print statement that outputs HTML tags such as <b> is really a formatting technique in CGI, just as using the backslash with n (\n) is formatting code.

When printing with variables and HTML tags, you can place the variable right in the middle of a print statement in quotation marks, and the variable is still recognized as such. For example, this next script segment would print She is bold and beautiful in boldface type:

$ugly = "beautiful";  print "<b>She is bold and $ugly .</b>"; 

Conditional Statements

Perl's conditional structures are very similar to those in JavaScript. The if, if / else, and if / elsif / else statements are almost identical, except that the key word elsif is spelled without an e. The following shows some conditional statements in a Perl script:

#!/usr/bin/perl  print "Content-type:text/html\n\n";  $alpha="Angels";  $beta="clouds";  $gamma="sky";  if (($alpha ne $beta) && ($gamma gt $beta)) {       print "$alpha live in $beta up in the $gamma .";        } else {       print "Where did all the angels go?";        }  exit; 

A big difference between Perl and JavaScript in conditional statements is that you must remember to use the numeric and string comparison operators correctly. In the previous example, note that the operators ne and gt were used instead of != and >, as would be done in JavaScript.

A different conditional structure that you will find in Perl but not JavaScript is the unless statement. It is the opposite of the if statement. When the condition is not true, the statement in the unless conditional executes, as the following shows:

#!/usr/bin/perl  print "Content-type:text/html\n\n";  $myDog="WillDe";  $goodDog="WillDe";  unless( $myDog ne $goodDog) {       print "Sit. Stay. Play the piano."; #This will appear on the screen.        }  exit; 

When going through a list of choices, each with a different outcome, use elsif. With CGI, this could be a common occurrence because several different values could be pulled out of a data file. The following example shows how elsif could be employed:

#!/usr/bin/perl  print "Content-type:text/html\n\n";  $nmLast="Smith";  $nmFirst="Karen";  if($nmLast eq "Smith" && $nmFirst eq "Ed") {       print "Hi Ed! How\'s the Smith family?";        }  elsif ($nmLast eq "Smith" && $nmFirst eq "Jacqueline") {       print "Hi Jackie! How\'s the Smith Flower Shop doing?";        }  elsif ($nmLast eq "Smith" && $nmFirst eq "Ralph") {      print "Hi Ralph! Congratulations on early parole!";  } else {        print "Gee, I don\'t think we\'ve met. Would you like to register with our         site?";  }  exit; 

In the example, the values for the two variables were assigned. However, the same script could be used if pulling data out of a text-data file.

Loops

Loops are important in Perl for searching through data files, as you will see in the next section. Loops in Perl and JavaScript share a good deal in common but, as with conditionals, you will see differences as well. The for loop has the same structure as the for loop in JavaScript:

for($counter;$counter < $min;$counter++) {       statements         }

Instead of using the for keyword, you can substitute foreach. They work identically, but one of the two might be clearer. For example, the following goes through a list and prints it to the screen:

#!/usr/bin/perl  print "Content-type:text/html\n\n";  foreach $customer("Tom","Dick","Harry") {       print "$customer<br>";  }  exit; 

The for statement could just as well have been used in the previous script, but the foreach keyword seems a little clearer in the context of going through the list of names. It also shows a very different loop construct than would be found in JavaScript. Each of the values in the variable is brought out almost like an array. However, as you can see, no array is declared.

The while loop in Perl is about the same as it is in JavaScript. The top of the loop contains the termination condition, and while that condition is not met, the loop iterates. The following is a simple generic example:

while ($counter < 10) {       print "Give me some JavaScript<br>";        $counter++;        } 

The until loop waits until a certain condition is met, looping until it is met. Note the differences between the following (until) and previous (while) script segments.

until ($counter == 10) {       print " Give me some JavaScript<br>";        $counter++;        } 

File Handling in Perl

One of Perl's attractions to designers is its capability to read and write text files. The attraction lies in the fact that designers can design their sites without having to set up a database (such as Access or MySQL) to store data. However, compared to PHP and ASP, in which the files are sophisticated relational databases, the files can be simple, plain-vanilla text files in a CGI page and Perl the kind you can create with Notepad or SimpleText. To get started, create a simple text file using Notepad, SimpleText, or your favorite text editor. Begin by creating a list of names, separated by commas, and save them as a text file named customers.txt, as in the following list:

Lisa,Marge,Homer,Bart,Maggie,Ned,Mo 

Place your text file on the server in the cgi-bin directory. Then, using CHMOD, initialize the file using 666 as the type. (With CHMOD 666, the owner, group, and everyone have read and write permissions, but none has the search/execute permission.) Next, type in the following script and save it as readData.pl:

#!/usr/bin/perl  print "Content-type:text/html\n\n";  open(CUS,"customers.txt");    #Open the file using CUS to identify the file  @cusList=<CUS>;               #Put the file contents into an array print @cusList;                          #Show on the screen what is in the file  close(CUS);                   #Close the file  exit; 

After you have saved the file, put it into the same cgi-bin directory as the text file. Initialize readData.pl with CHMOD 755, and then open your browser and execute the script. You will see exactly what you put into the text file.

Now that you can see how easy it is to read and display the contents of a text file using Perl in a CGI page, you need to understand some very basic Perl statements and structures behind the process.

The open Function

The open function in Perl requires, at a minimum, only two arguments a file reference name and the actual file's URL. The file reference name (filehandle) can be any name that you want, and it works like a nickname for the actual file. The basic format is the following:

open(fileHandle, "fileName.xxx"); 

When both the CGI page and the data file are in the cgi-bin directory, the URL is simply a filename, as shown in the example in the previous section. The file reference name or filehandle is conventionally capitalized; if you prefer, you can use the program's normal input channel name, STDIN. However, generally, you want to have a filehandle that is somehow associated with the file's contents or name.

When you open a file using Perl, you have three key options (among others):

  • Read the file:

    Open(MYFILE, "fileName") 
  • Create a file and write to it:

    Open(MYFILE, ">fileName") 
  • Append an existing file:

    Open(MYFILE, ">>fileName") 

Using write and append

Writing to a new file or appending an existing one is quite simple with Perl. Keeping in mind that most users will be appending existing files rather than creating new ones, the following two examples show the steps in first creating a new file and then appending the file. The sample file is a corporate one for the names and duties of personnel in an organization. Later, in using a single separator, a space, Perl will reformat the string for a clear output to the screen.

  1. Create a text file and save it as posData.txt, but do not put anything in the file. Place the file into the cgi-bin directory, and initialize it with CHMOD 666.

  2. Create a file to write data to the posData.txt file using the following script. (If you substitute names and positions in the $name or $job variable, be sure to keep any spaces out of the name or position. Use underscores [_] to connect the names or dashes [-] for the job title to create a string with no spaces.)

    #!/usr/bin/perl  print "Content-type:text/html\n\n";  $name="Daniel_Gonzalez";  $job="programmer";  open(JOBS,">posData.txt");  #Include one space after $name and $job.  #The first print goes to the file, not the screen.  print JOBS "$name $job ";  close(JOBS);  #The second print goes to the screen.  print "Data added to file.";  exit; 

    Save the file as write.pl, and put it into the cgi-bin directory. Initialize it with CHMOD 755. Test the script in your browser. After you have successfully launched the script, check the text file posData.txt. You should see this in the file:

    Daniel_Gonzalez programmer 
  3. The append script is identical except for the values of the strings and the double arrow-bracket in the open function:

    #!/usr/bin/perl  print "Content-type:text/html\n\n";  $name="Nancy_Rogers";  $job="marketing-manager";  open(JOBS,">>posData.txt");  #Include one space after $name and $job.  #The first print goes to the file, not the screen.  print JOBS "$name $job ";  close(JOBS);  #The second print goes to the screen.  print "Data appended to file.";  exit; 

    Save the script as append.pl, move it to the cgi-bin directory, and initialize it with CHMOD 755. Run the script in your browser. Again, open the posData.txt file in cgi-bin. This time you should see the following:

    Daniel_Gonzalez programmer Nancy_Rogers marketing-manager

Having seen how to read files and write and append them using Perl and CGI, the next step is to read the files created with write and append and format the output. This last step is what Perl does well using very powerful pattern-recognition operators and functions. The next section examines Perl's regular expressions and pattern matching but, at this point, only the most simple formatting will be used, in an effort to clarify the process of formatting data with Perl.

Formatting with the split() Function

One of Perl's built-in functions, split(), can be used to divide up a string into multiple substrings. These substrings then are placed into an array and formatted for output. The general split() format used in the next example to cut up a string into array elements and place them into an array is as follows:

@arrayName = split(/character/,$stringName) 

Basically, split() chops up the string along the lines that you specify in the pattern matching (character between the two slashes). Each array element is stripped of the matched character so that each element contains the substring between the matched characters. Because the data entered in the previous write and append examples used a space to separate both the name and the position, the names and positions are disconnected substrings. However, because the substrings (or elements in the array) contain names and positions in order of their connection to one another, by taking every other element in the array, it is possible to format and output them in a way that is connected. Try out the following script, and afterward go through the script analysis.

format.pl
#!/usr/bin/perl  print "Content-type:text/html\n\n";  open(POS,"posData.txt");  #Place the data into a scalar variable ($posn).  $posn=<POS>;  #Use the split function to divide up the parts by spaces (/ /) to be placed in an array.  graphics/ccc.gif(@posnS).  @posnS=split(/ /,$posn);  #Step through every other element in array to group output by name and position.  for($i=0;$i<=$#posnS;$i+=2) {        #Replace underscores and dashes with spaces.         $posnS[$i] =~ tr/_/ /;         $posnS[$i+1] =~ tr/-/ /;         print "$posnS[$i] position title is > $posnS[$i+1]<br>";         }  close(POS);  exit; 

Save the script, put the script file into the cgi-bin directory, and initialize it with CHMOD 755. When you run it from your browser, you will see this:

Daniel_Gonzalez position title is > programmer  Nancy_Rogers position title is > marketing-manager

As you append more names and positions, the output automatically will format it in this order and arrangement, adding new entries to the bottom of the list.

In looking at the script, the key points are in the lines that split the string and put it into an array, and the loop that pulls out the array elements and puts them on the screen. The first of these two key script lines is

@posnS=split(/ /,$posn); 

The array @posS is made up of the scalar variable $posn, cut up into substrings at the split character. A blank space between the two slashes means that a blank space is the character where the string is cut up into substrings.

After the big string is broken into substrings and placed into an array, the next task is to pull each element out of the array and provide a format for output. In this case, a loop is used:

for($i=0;$i<=$#posnS;$i+=2) {       print "$posnS[$i] position title is > $posnS[$i+1]<br>";        $posnS[$i] =~  tr/_/ /;        $posnS[$i+1] =~ tr/-/ /;        } 

The general way to find the length of an array minus 1 is to use this statement:

$#arrayName 

To find the length of the array of @posnS for the termination condition in the for loop, use the statement $#posnS. The increment is set to 2 because the names are going to appear in only every other element. This expression does the trick for you:

$i += 2 

Because the position follows the names, it is the next element value. Thus, the position is acquired by this expression:

$posnS[$i+1] 

A line break tag <br> is placed after the position to create an orderly list.

Regular Expressions

The sine qua non of Perl is its regular expressions. Regular expressions are the codes used to specify a pattern that is to be matched with data. In the previous script used with the split() function, the regular expression operators / / looked for a matching space in the data. All patterns in Perl express a pattern by placing the pattern between two slashes. For example, the following are all legitimate patterns in regular expressions:

/55/  /word/  /The stuff that dreams are made of/ 

The pattern matches if the string between the slashes matches a substring (a string segment) in the comparison data.

When you need to find several different matching strings, use the vertical bar ("pipe") character to separate the search elements. For example, the following has four patterns that can be matched with the data:

/honesty|integrity|persistence|wisdom/ 

Some Fundamental Operators in Regular Expressions

Perl has a number of different operators that can be used in regular expressions, but the most basic are the following:

  • =~ Contains (matches)

  • !~ Doesn't contain (doesn't match)

The matches work on a Boolean principle and are evaluated as true or false. As a result, you will find them used extensively in conditional statements. For example, the following conditional script looks to see whether a compound match exists and branches a certain way, depending on the outcome:

#!/usr/bin/perl  print "Content-type:text/html\n\n";  $application="some experience low scores";  if ($application =~  /experience|high scores/) {       print "You're hired!";  } else {       print "We'll let you know.";        }  exit; 

The script compares the string $application with the match pattern. Because the word experience is contained in the string and the pattern, the expression evaluates as true.

You can also use regular expressions to substitute one substring for another. The format is

$stringName =~ s/oldString/newString/ 

The oldString pattern is sought in the string ($stringName) and, if found, the newString replaces the oldString substring. The following example illustrates one use of substitution:

#!/usr/bin/perl  print "Content-type:text/html\n\n";  $thankYou="Thank you for your gift.";  $amount=200;  if($amount > 150) {       $thankYou=~  s/gift./generous gift!/;        }  print "$thankYou";  exit; 

If you want to substitute one character for another, use this format:

tr/oldCharacter/newCharacter/ 

The only difference between using tr/// (transliteration) and s/// is that tr/// scans a string one character at a time. However, you can put in ranges of characters, such as

tr/a-p/A-P/ 

Here, all lowercase characters in the range from a to p will be capitalized.

Perl also has pattern modifiers. The most important for designers might be the non case-sensitive modifier /i. By placing the /i modifier at the end of a pattern, the letter cases will be ignored. For example, the following script excerpt would result in a match:

$bigshot = "HOT STUFF";  if($bigshot =~ /hot/i) { . 

In most instances, Perl is case-sensitive, so, without having the capability to ignore cases in a match, you'd have a good deal more coding to make sure that a match was not ignored because of case.

Passing Data to CGI from HTML

In the previous sections in this chapter, you saw how to place data into a data file and how to pull it out and format it for the screen (format.pl). Using an HTML form and JavaScript, you can create a page that makes it easy to enter the data that you want and have it written to a text file stored in cgi-bin. You can also use JavaScript to help you preformat the data so that it will be easier to pull out and format using Perl.

Setting Up the Front End

The "front end" is where the user interfaces with the data. She enters the data, and it is passed to a CGI page and then written to a text file in a specific format. The interface also should have a means to read the data in the file. Thus, you will probably want to use frames. One frame will be used for data entry and providing buttons to read the data. The other frame is used for displaying data from the text file. A common external CSS file uses a French color pattern from Leslie Cabarga's Designer's Guide to Global Color Combinations (North Light Books, 2001).

filePass.css
h2 { text-align:center;        font-size:18pt;        font-family:verdana;        color:#e00021;        background-color:#b8bab9;        font-weight:bold        }  #labels { font-family:verdana;        color:#b8bab9;        background-color:983094;        font-size:11pt;        font-weight:bold        }  a {       font-family:verdana;        color:#b8bab9;        background-color:983094;        font-size:11pt;        font-weight:bold;        text-decoration:none        }

Next, you need to set up the frameset. With only two frames, the task is an easy one.

dataSet.html
<html>  <frameset cols="*,*" frameborder=0, border=0>  <frame name="dataIn" src="appendData.html" frameborder=0 border=0>  <frame name="dataOut" src="showData.html" frameborder=0 border=0>  </frameset>  </html>

The next segment of the front end is the core. It uses JavaScript to help format the data. Usually, some kind of verification would be included in the JavaScript as well, but, in this example, I wanted to focus on formatting text. The first JavaScript function simply adds an underscore character to link the first and last names. The second function looks for a space between any words in the window and places a dash between them, if one is found. Note how a regular expression, very much like the ones in Perl, is used in the second JavaScript function to add a dash (-) where any spaces exist. One of the two Perl scripts that accompanies this set called (format.pl) was used previously in this chapter. The JavaScript formatting sets up the data sent to the CGI page so that the format.pl script can be used again.

<html>  <head>  <link rel="stylesheet" href="filePass.css" type="text/css">  <title>Append Data to an existing data file </title>  <script language="JavaScript">  function addUS() {       var firstForm=document.top;        var secondForm=document.bottom;        var fullName=firstForm.fName.value + "_" + firstForm.lName.value + " ";        secondForm.wName.value=fullName;        }  function checkPos() {       var t= document.top;        var b=document.bottom;        var spacer=t.position.value;        //Use a regular expression to swap spaces for dashes        var fixer= spacer.replace(/ /g,"-");        b.positionF.value=fixer;        }  //Put both functions together into a whole  function fixAll() { addUS();  checkPos();  }  </script>  </head>  <body onLoad="document.forms[0].reset()" bgColor="#528490">  <h2>Fill in the form with your name and position.</h2>   <div ID="labels">  <form name="top">        Enter first and last names:<br>        <input type=text name="fName">        <input type=text name="lName"><br>        Enter your position:<br>        <input type=text name="position">  </form>  </div>  <form name="bottom" method=POST action="http://www.sandlight.com/cgibin/  formAppend.pl"onSubmit="fixl  ()" target="dataOut">        <input type=hidden name="wName">        <input type=hidden name="positionF">        <input type=submit>  </form><p>  <a href="http://www.sandlight.com/cgi-bin/format.pl" target="dataOut">View Data  </a></p>  </body>  </html>

The two functions preprocess the data and store it in the second, hidden form. The data in the hidden form are sent to the CGI page. Before explaining what happens in the CGI page, the frameset needs to be completed with a "holding page" for the data that will appear in the frame later.

showData.html
<html>  <head>  <link rel="stylesheet" href="filePass.css" type="text/css">  </head>  <body bgcolor="#983094">  <h2>Data appears in this window:</h2>  </body>  </html>

That's all of the front end that has to be created. However, you must think of front ends and back ends always working together. So, the back end or server-side script in Perl must be matched to the type of data and method (POST or GET) used to send the data. This next section explains how things work on the CGI end of the equation.

Front-End and Back-End Connections: Interpreting Form Data in Perl

When you use a form to send data, it can be sent using the POST or GET methods. When data are sent using GET, this line places the data into a scalar variable:

$data=$ENV{'QUERY_STRING'}; 

If, as has been done in this example, your method is POST, you use this line to place data into a specified scalar variable:

read(STDIN, $data, $ENV{'CONTENT_LENGTH'}); 

(In this example, $data is used, but you can use any name you want.)

Because POST was used, the second of the two standard remote "data-catching" lines was employed in the script. The web sends a big hash called %ENV to CGI when a CGI script executes. All environmental variables are stored in the hash, and the line $ENV{'CONTENT_LENGTH'} specifies which environmental variable to use in this case, CONTENT_LENGTH.

STDIN is a keyword in Perl for "standard input," and it specifies the standard input channel used to send data to a CGI script. So, basically, the line channels in data in the POST format and drops it into a scalar variable of your choice. Whether your form has 1 or 100 windows of data, all that Perl sees is one big string to make sense of. That's what will be stored in $data (or whatever name you use for a scalar variable).

Using the input line to extract data sent from an HTML form, the rest of the work for the Perl script is to format it using regular expressions for storage in a text file. This next script does exactly that:

#!/usr/bin/perl  print "Content-type:text/html\n\n";  read(STDIN, $fromPost, $ENV{'CONTENT_LENGTH'});  open(JOBS,">>posData.txt");  #Data from form is stripped of input names  $fromPost =~  s/wName=//;  $fromPost =~  s/\+&positionF=/ /;  $fromPost .= " ";  #Data is sent to text file using print statement  print JOBS "$fromPost";  close(JOBS);  #Let the viewer know the data are appended.  print "Data appended to file.";  exit; 

NOTE

As soon as you write to a file, it clears all the records from the file. Therefore, you want to have some kind of existing file to append data to. The easiest way is to create an empty text file, save it in the cgi-bin directory, and use CHMOD 666 to initialize it. Then the file can be appended indefinitely.

Special characters are used to separate the form names when sent from the HTML form to the CGI page. Depending on the input form element names you used, you will be stripping different names than the ones shown previously. However, it is advisable to keep your form name short and clear when dealing with CGI pages, to make it easy on yourself when removing them from the data.

To finish up, all you need to do is to call on the script format.pl that was used in a previous section. (See the earlier section "Formatting with the split() Function.") It will read the data and present it in the right window of the frameset. Figure 16.2 shows the pages displayed in a browser window.

Figure 16.2. JavaScript, HTML, CGI, and Perl work well together.

graphics/16fig02.gif

Summary

JavaScript plays a secondary role between forms and CGI pages, but it can be an excellent preprocessor for use with CGI scripts. Besides being used for verification, JavaScript can be used for preformatting data to be sent to a CGI script for placement into data files. The preformatting can make it easier to create a script that will store and retrieve the data for clearly formatted display.

Perl is a very rich language, and this chapter has just scratched the surface of working with CGI and Perl. Several good books on Perl and CGI are available, and the third edition of Programming Perl (O'Reilly, 2000) is a thorough resource for learning much more about Perl and its relationship to CGI and HTML. The wide range of regular expressions in Perl helps to understand and fully use regular expressions in JavaScript as well.

CONTENTS


JavaScript Design
JavaScript Design
ISBN: 0735711674
EAN: 2147483647
Year: 2001
Pages: 25

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net