1.91k likes | 2.09k Views
More CGI programming. Back to CGI programming. Now that we know how to use conditional expressions, we can write a CGI program that determines whether the environment variables set by the HTTP server demon include one of interest. CGI program which checks for a particular env var.
E N D
Back to CGI programming ... • Now that we know how to use conditional expressions, we can write a CGI program that determines whether the environment variables set by the HTTP server demon include one of interest
CGI program which checks for a particular env var #!/usr/local/bin/perl print <<EOF; Content-type: text/html <HTML> <HEAD><TITLE> Environment checking program </TITLE></HEAD> <BODY> <H1> Environment Variables </H1> <p> EOF # next line checks if a certain key/value pair in %ENV is defined if ( $ENV{”HTTP_GROCERY_ORDER"} ) { print ”Request includes Grocery-Order header" } else { print “Request does not include Grocery-Order header”}; print <<EOF; </p> </BODY> </HTML> EOF
Defining subroutines in Perl • A subroutine definition in Perl is of the form sub <subroutine-name> { <sequence-of-statements> } • Example sub greetTheWorld { print “Hello, world!\n”; print “Have a nice day” } • In a main program, this would be called as follows: greetTheWorld();
Defining subroutines in Perl (contd.) • Another example sub printEnvironmentVariables { foreach my $key ( sort( keys(%ENV) ) ) { print "<LI> $key = $ENV{$key}</LI>" } } • This is used on the next two slides in a new version of the CGI program which prints out its environment variables
A revised CGI program to report env vars (Part 1) #!/usr/local/bin/perl print <<EOF; Content-type: text/html <HTML> <HEAD> <TITLE> Environment reporting program </TITLE> </HEAD> <BODY> <H1> Environment Variables </H1> <UL> EOF printEnvironmentVariables(); print <<EOF; </UL> </BODY> </HTML> EOF
A revised CGI program to report env vars (Part 2) sub printEnvironmentVariables { foreach my $key ( sort( keys(%ENV) ) ) { print "<LI> $key = $ENV{$key}</LI>" } }
Passing Arguments to subroutines • The subroutines which we have defined so far have not taken any arguments • Pre-defined Perl subroutines can take arguments, as in this program fragment: %mothers = (Tom=>May, Bob=>Ann, Tim=>Una); delete( $mothers{Bob} ) • Can programmer-defined subroutines take arguments? • Yes, although the way in which they handle arguments is a little different from what you are used to
Passing Arguments to subroutines (contd.) • Suppose we want a subroutine called greetPerson which • takes one argument, a string, and • prints a message greeting the person whose name is the string • An example call might be greetPerson(“Eamonn de Valera”) which should produce the output Hello, Eamonn de Valera • The following program fragment should produce the same output: my $person = “Eamonn de Valera”; greetPerson($person) • How would we define such a subroutine?
Passing Arguments to subroutines (contd.) • Your first instinct might be to write something like this: sub greetPerson($formalArgument) { print “Hello, $formalArgument” } but that would be WRONG • A subroutine in Perl must access its actual argument(s) through a special array variable called @_ • Since our subroutine takes only one argument, this would be in the first element of @_, so our definition would be: sub greetPerson { print “Hello, $_[0]” }
Passing Arguments to subroutines (contd.) • Suppose we want a subroutine called greetTwoPeople which • takes two string arguments and • prints a message greeting the people whose names are the strings • An example call might be greetTwoPeople(“Eamonn”, “Michael”) which should produce the output Hello, Eamonn and Michael • Since our subroutine takes two arguments, these would be in the first two elements of @_, so our definition would be: sub greetTwoPeople {print “Hello, $_[0] and $_[1]”}
Passing Arguments to subroutines (contd.) • Suppose we want a subroutine called greetMember which • takes two arguments • an array of strings • an integer pointing to one member of this array • and prints a message greeting the person whose name in the indicated string • An example use is: @club = (Eamonn, Michael, Harry); greetMember(2, @club) which should produce the output Hello, Michael • This introduces a further complication ...
Passing Arguments to subroutines (contd.) • All actual arguments to a subroutine are collapsed into one flat array, the special array @_ • Thus, the program fragment @club = (Eamonn, Michael, Harry); greetMember(2, @club) causes the subroutine greetMember to receive an @_ whose value is (2, Eamonn, Michael, Harry) • So our definition would be: sub greetMember { print “Hello, $_[$_[0]]” }
Using local variables in subroutines • Local variables can be defined in subroutines using the my construct • Indeed, doing so enables us to write subroutines which are easier to understand • subroutine greetMember on the last slide is clearer if it written using local variables, as follows: sub greetMember {my ($position, @strings); $position = $_[0]-1; @strings = @_[1..scalar(@_)-1]; print “Hello, $strings[$position]” }
Using local variables in subroutines • We don’t have to declare the local variables in a separate line • We can just use the my construct in the statements where the vars first appear • The subroutine greetMember on the last slide could also be written as follows: sub greetMember {my $position = $_[0]-1; my @strings = @_[1..scalar(@_)-1]; print “Hello, $strings[$position]” }
Using local variables in subroutines • We can also use a subroutine called shift() to remove the first element from @_ • Since shift() also returns, as its value, the value of the removed element, we can use it in an assignment statement • Since have removed the first element, we can then assign the new value of @_ to @strings • The subroutine greetMember on the last slide could also be written as follows: sub greetMember {my $position = shift(@_); my @strings = @_; print “Hello, $strings[$position]” }
Using local variables in subroutines • What I regard as an unfortunate feature of Perl is that it allows a lot of abbreviations • I present one here, simply because you will often see it in script archives • if no explicit argument is given to shift() in a subroutine, it is assumed to be @_ • Thus, in a script archive, you might find subroutine greetMember on the last slide written as follows: sub greetMember {my $position = shift; my @strings = @_; print “Hello, $strings[$position]” }
subroutines which return values • We often need to define subroutines which return values, as in the following program fragment: my @numbers = (1, 2, 3, 4, 5); my $average = sum( @numbers ) / scalar( @numbers ); print $average • It can be defined as follows: sub sum { my @numbers = @_; my $sum = 0; foreach my $value ( @numbers) { $sum = $sum + $value } return $sum } • The value returned is specified with a return statement
subroutines which return values (contd.) • A subroutine can contain more than one return statement • The following program fragment defines and uses a boolean subroutine which checks for the existence of the argument passed to it if ( present ( $ENV{"EDITOR"} ) ) { print "\n The envVar EDITOR exists" } else { print "\n The envVar EDITOR does not exist" }; sub present { my $varInQuestion = $_[0]; if ( $varInQuestion ) { return 1 } else { return 0 } } • It enables us to write a cleaner version of a CGI program we wrote earlier
Revised CGI program which checks for an env var (part 1) #!/usr/local/bin/perl print <<EOF; Content-type: text/html <HTML> <HEAD><TITLE> Environment checking program </TITLE></HEAD> <BODY> <H1> Environment Variables </H1> <p> EOF if ( present($ENV{”HTTP_GROCERY_ORDER"}) ) { print ”Request includes Grocery-Order header" } else { print “Request does not include Grocery-Order header”}; print <<EOF; </p> </BODY> </HTML> EOF
Program reporting GET method data • We will use much of what we have learned to write a CGI program which • is called by a HTML FORM • and sends back to the browser a HTML page which lists the data it received from the form
Program reporting GET method data (part 1) #!/usr/local/bin/perl print <<EOF; Content-type: text/html <HTML> <HEAD> <TITLE> Program reporting GET method data </TITLE> </HEAD> <BODY> <H1> Form Data sent by the GET method </H1> <UL> EOF printFormData(); print <<EOF; </UL> </BODY> </HTML> EOF
Program reporting GET method data (part 2) sub printFormData { my $queryString = $ENV{'QUERY_STRING'}; separateAndPrintDataIn($queryString) } sub separateAndPrintDataIn {my (@equations, $name, $value); @equations = split("&",$_[0]); foreach my $equation (@equations) { ($name,$value) = split("=",$equation); print ”<LI>$name = $value </LI>"; } }
Decoding query strings • The previous program was pretty good but it would not work in all cases • Suppose the program is called by a HTML FORM which contains two text input elements: • one asks for the user’s name • one asks for the company for which he works
Decoding query strings • Suppose the user’s name is Sean Croke and his company’s name is Black&Decker • The QUERY_STRING received by the program will be name=Sean+Croke&company=Black%26Decker because space in the user’s name and the ampersand in the company’s name must be encoded for safe transmission • separateAndPrintDataIn must be improvedto cater for this • We must learn more about string processing in Perl to do this
String Processing in Perl • Perl contains a facility for reasoning about regular expressions, expression that describe classes of strings • Since dynamic web page generation is all about text processing, Perl’s regular expression tools are probably the most important reason why the language has become so widely used in server-side web programming • We will not have time in this course to cover all of Perl’s regular expression facilities • We will consider only a subset, including those facilities that are required by the form-data processing task we have set out to achieve
Retrieving encoded SP characters • To retrieve the SP characters that encoded in the QUERY_STRING, we need to learn about only two operators • the translation operator tr/// • the binding operator =~ • Consider the following Perl statement $stringVar =~ tr/+/ /; • The binding operator =~ says that the translation expression tr/+/ / should be applied to the contents of $stringVar • The translation expression tr/+/ / specifies that every instance of the + character should be replaced by a SP
The tr/// operator • In general, an application of the tr/// operator is of the form tr/<list1>/<list2>/ where <list1> and <list2> are (rather simple) reg exprs specifying ordered character lists of equal length • It specifies that instances of character N in <list1> should be replaced by the corresponding character in <list2> • Example: tr/abc/cab/ replaces any instance of a by c, any instance of b by a and any instance of c by b • Example tr/A-Z/Z-A/ replaces uppercase letters with the corresponding letters in a reverse-order alphabet
Retrieving encoded SP characters (finally!) • This is the revised definition of separateAndPrintDataIn sub separateAndPrintDataIn {my (@equations, $name, $value); @equations = split("&",$_[0]); foreach my $equation (@equations) { ($name,$value) = split("=",$equation); $value =~ tr/+/ /; print ”<LI>$name = $value </LI>"; } }
Decoding URL-encodings • The revised definition of separateAndPrintDataIn on the previous slide will handle the+char in a QUERY_STRING like name=Sean+Croke&company=Black%26Decker but it will not decode the URL-encoding in %26 • We need to modify the subroutine still further so that, whenever it finds a % followed by two hexadecimal digits it will replace these three characters by the single character whose URL-encoding this three-character sequence represents • We need to learn some more Perl
The s/// operator • A basic application of the s/// operator is of the form s/<pattern>/<replacement>/ where <pattern> is a regular expression and <replacement> is treated as if it were a double-quoted string • which means that <replacement> can contain variables, some of which may be assigned values while <pattern> is matched with the target string • The operator specifies that the first instance of <pattern> should be replaced by the corresponding interpretation of <replacement>
The s/// operator (contd.) • Example s/// expression: s/ab*c/ac/ this replaces the first substring of the target string that comprises “an a followed byzero or more instances of b followed by by a c” with the substring “ac” • Example application of the above s/// expression: $myString = “adabbbbcabbcabceee”; print “myString is $myString\n”; $myString =~ s/ab*c/ac/; print “myString is $myString” • This produces the following output myString is adabbbbcabbcabceee myString is adacabbcabceee
The s/// operator (contd.) • We have seen that certain characters have a special meaning in regular expressions: • the example on the last slide used the * character which means “0 or more instances of the preceding character or pattern” • These are called meta-characters • Other meta-characters are listed on the next slide
The s/// operator (contd.) • The meta-characters include: • the * character which means “0 or more instances of preceding” • the + character, which means “1 or more instances of preceding” • the ? character, which means “0 or 1 instances of preceding” • the { and } character delimit an expression specifying a range of acceptable occurrences of the preceding character • Examples: {m} means exactly m occurences of preceding character/pattern {m,} means at least m occurrences of preceding char/pattern {m,n} means at least m, but not more than n, occurrences of preceding char/pattern • Thus, {0,} is equivalent to * {1,} is equivalent to + {0,1} is equivalent to ?
The s/// operator (contd.) • Further meta-characters are: • the^ character, which matches the start of a string • the $ character, which matches the end of a string • the . character which matching anything except a newline character • the [ and ]character starts an equivalence class of characters, any of which can match one character in the target string • the( and ) characters delimit a group of sub-patterns • the| character separates alternative patterns
The s/// operator (contd.) • Example s/// expression: s/^a.*d$/x/ this replaces the entire target string with “x”, provided the target string starts with an a, followed by zero or more non-newline characters, and ends with a d • An example application is on the next slide
The s/// operator (contd.) • Example application of the s/// expression on the last slide: $myString1 = “adabbbbcabbcabcede”; print “myString1 is $myString1\n”; $myString1 =~ s/^a.*d$/x/; print “myString1 is $myString1\n” print “\n”; $myString2 = “adabbbbcabbcabceed”; print “myString2 is $myString2\n”; $myString2 =~ s/^a.*d$/x/; print “myString2 is $myString2” • This produces the following output myString1 is adabbbbcabbcabcede myString1 is adabbbbcabbcabcede myString2 is adabbbbcabbcabceed myString2 is x
The s/// operator (contd.) • Example s/// expression: s/^a.{2,5}d$/x/ this replaces the entire target string with “x”, provided the target string starts with an a, followed by between two and five non-newline characters, and ends with a d • An example application is on the next slide