blind folio oracle series / oracle9iweb development / brown / 9388

25
Web 1 Perl and the Perl Module

Upload: others

Post on 12-Sep-2021

5 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Blind Folio ORACLE Series / Oracle9iWeb Development / Brown / 9388

ORACLE Series / Oracle9i Web Development / Brown / 9388-3 / Chapter 1Blind Folio 1:1

Web1

Perl and thePerl Module

P:\010Comp\Oracle8\388-3\Web1.vpThursday, October 04, 2001 12:36:53 PM

Color profile: Generic CMYK printer profileComposite Default screen

Page 2: Blind Folio ORACLE Series / Oracle9iWeb Development / Brown / 9388

If you’re looking for an interpretive programming language thatoptimizes the scanning of arbitrary text files to extract informationfor printing reports, or if you’re looking for a good language to handlefile operations or system management tasks, Perl might be the toolfor you. If you’re using Java as your primary development tool, but

you need to access databases that aren’t supported by JDBC, Perl might be thesolution you want.

Perl is a powerful and portable interpretive scripting language. While aninterpretive language is slower than a compiled language (such as C), interpretivelanguages such as Perl, Java, C#, JavaScript, and so forth are easily ported acrossplatforms. Because Perl is an interpretive language, you can use a simple text editor(for example, Notepad, vi, Write, or Word) for code development, but you’ll needa Perl interpreter to run your Perl scripts. Perl’s syntax is similar to the syntax of C,but Perl has less restrictive specifications. For example, in Perl you aren’t required todeclare or initialize variables. If you already know C, the concepts and intricacies ofPerl can be obtained effortlessly. If you don’t know C, you’ll be delighted to knowPerl is easier to learn than C. For example, string manipulation and arraysare nearly effortless in Perl. If you’re a Java programmer, you’ll find Perl similarbecause Java is also based on the C syntax. Perl combines the best features ofUnix shell scripting, C programming, and the Unix utilities (sed, awk, and grep)to make a powerful programming language.

Perl was often referred to as a Common Gateway Interface (CGI) for Webdevelopment. Perl was developed long before the Web became popular. Whilepeople seem to mention Perl in association with Web development, it’s a powerfulserver-side tool, as well. Perl is truly a portable language that runs on a varietyof platforms. Perl also supports direct access to many databases including theOracle database. The database interface for Perl—called the Perl DatabaseInterface Module or DBI—was written by Tim Bunce. Perl is available on Unixand Win32 environments, and, best of all, it’s free. Larry Wall, the author of Perl,still holds the copyright.

TIPIf you want to meet Larry Wall in person, I know ofa place where you can do this. He goes on the PerlWhirl Geek Cruise (http://www.geekcruises.com)every year. Tim Bunce, Mark-Jason Dominus,Lincoln Stein, Damian Conway, Nathan Torkington,and Randal Schwartz (author of Learning Perl—known as “the Llama book”) also attend thisconference/cruise.

Oracle9i Web Development

ORACLE Series / Oracle9i Web Development / Brown / 9388-3 / Web 1Blind Folio 1:2

P:\010Comp\Oracle8\388-3\Web1.vpThursday, October 04, 2001 12:36:54 PM

Color profile: Generic CMYK printer profileComposite Default screen

Page 3: Blind Folio ORACLE Series / Oracle9iWeb Development / Brown / 9388

In this chapter, you learn about the following tips and techniques:

■ Learning Perl

■ Downloading a Newer Version of Perl and mod_perl

■ News and Resources for mod_perl

■ Running Perl Scripts from a Specific Directory

■ Turning on the .pl Extension Everywhere

■ Turning on the Perl Status

■ Running OWA from Perl

■ Accessing Oracle from Perl

■ DBD Interfaces Available

■ Testing and Debugging Perl

■ Using a Standard CGI Library

■ Displaying a List of Files

■ Determining if a File Exists

■ Creating or Appending a File

■ Invoking a PL/SQL Procedure from Perl

■ Emulating a Browser from the Command Line

■ Emulating a POST Request from the Command Line

■ Cleaning Up Your HTML

■ Getting Access to Perl Documentation

■ Looking at the Environmental Parameters

■ Sending Mail from Perl

■ Determining the Client Browser and Acting Accordingly

■ Including Site Components

■ Accessing Oracle (Sample Code)

■ Understanding the Perl Startup File

■ Making Database Connections Persistent

■ Reviewing Production OraPerl Code

■ Sites that Provide Perl Information

Perl and the Perl Module

ORACLE Series / Oracle9i Web Development / Brown / 9388-3 / Web 1Blind Folio 1:3

P:\010Comp\Oracle8\388-3\Web1.vpThursday, October 04, 2001 12:36:54 PM

Color profile: Generic CMYK printer profileComposite Default screen

Page 4: Blind Folio ORACLE Series / Oracle9iWeb Development / Brown / 9388

Learning PerlYou might wonder why you should bother learning Perl. If you’re developingapplications using iAS, PL/SQL might provide all the flexibility you need to developpowerful, robust, dynamic Web applications. While this is probably true 95 percentof the time, you need to consider that other 5 percent. You can choose to use Java for99 percent of your development or you might choose to use PL/SQL for 95 percent ofyour code and Perl for the other 5 percent. No matter what language you choose, thatlanguage probably won’t serve 100 percent of your programming needs.

For example, Perl’s database interface (DBI) supports a number of databases thataren’t supported by Java’s database interface (JDBC). Perl is free. If you aren’t usingiAS, Perl works well for Web development, and can access the Oracle database(and others), so Perl might be the programming tool of choice for you. If you areusing iAS’s PL/SQL module, the following might be an example of a situation fallinginto that 5 percent previously mentioned.

In a typical production configuration, the Web server resides outside the firewalland the database is inside the firewall. If your database resides on one server and yourWeb server resides on another, the Oracle database engine can access files on thedatabase server using PL/SQL, but not on the Web server. Given the same situation,Perl enables you to access the Web server’s file system, but not the database server’sfile system. The capability to interact with a file system to read password files orcompare directory trees can be useful when developing secure applications. The serverfrom which you need to access flat files dictates which tool will serve your needs.

Perl can also fill the PL/SQL gap when running an operating system program(for example, Sendmail) from your application. Perl can call operating systemcommands and programs, while PL/SQL cannot. Java and Perl can both calloperating system commands.

Many great books are available to review the Perl language in detail. For example,Programming Perl, by Larry Wall, Tom Christiansen, and Jon Orwant (O’Reilly, 2000),Perl Cookbook, by Tom Christiansen, Nathan Torkington, and Larry Wall (O’Reilly,1998), and Learning Perl, Third Edition, by Randal L. Schwartz and Tom Phoenix(O’Reilly, 2001) are all excellent books. Unless you’re developing 100 percent of yourcode with the Perl module, you’ll probably want to select one or two developers whocan code you right through the situations where Perl is required. If you’re a Perl shop,Perl under iAS is regular Perl based off the 5.005_03 build of Perl.

Downloading Newer Versionof Perl and mod_perlThe current production release of Perl is 5.6.1. The current experimental release is5.7.1. Both versions can be downloaded from http://www.perl.com/pub/language/

Oracle9i Web Development

ORACLE Series / Oracle9i Web Development / Brown / 9388-3 / Web 1Blind Folio 1:4

P:\010Comp\Oracle8\388-3\Web1.vpThursday, October 04, 2001 12:36:54 PM

Color profile: Generic CMYK printer profileComposite Default screen

Page 5: Blind Folio ORACLE Series / Oracle9iWeb Development / Brown / 9388

info/software.html. The latest version of mod_perl can be found at http://perl.apache.org/dist/. iAS is built with mod_perl version 1.22.

News and Resources for mod_perlYou can find a great newsletter to keep you current on mod_perl at http://take23.org/.This site also includes great documentation, articles, and news on mod_perl.

Running Perl Scripts from aSpecific DirectoryTo run Perl from a specific directory, you must first establish the virtual path for thedirectory that contains the Perl programs. As described in Chapter 3, virtual pathsare defined with the Alias command in the httpd.conf file. You can specify avirtual path that directly references the Perl directory or the Perl files can be in asubdirectory of a virtual directory. For example, if the virtual path for the directoryis established as

Alias /websites/ “c:\websites/”

Under the Websites directory, if a directory named perl contains our Perlprograms, the following Location directive tells iAS to run the Perl scripts in thisdirectory:

<Location /websites/perl>SetHandler perl-scriptPerlHandler Apache::RegistryAddHandler perl-script .plOptions +ExecCGIPerlSendHeader On

</Location>

After adding these entries to the configuration file (httpd.conf), you need torestart iAS for these directives to take effect.

If you define the exact directory that houses the Perl scripts with an Alias, suchas the following,

Alias /perl/ “c:\websites/perl/”

the Location directive would simply change its first line as follows:

<Location /perl>

Perl and the Perl Module

ORACLE Series / Oracle9i Web Development / Brown / 9388-3 / Web 1Blind Folio 1:5

P:\010Comp\Oracle8\388-3\Web1.vpThursday, October 04, 2001 12:36:55 PM

Color profile: Generic CMYK printer profileComposite Default screen

Page 6: Blind Folio ORACLE Series / Oracle9iWeb Development / Brown / 9388

Oracle9i Web Development

ORACLE Series / Oracle9i Web Development / Brown / 9388-3 / Web 1Blind Folio 1:6

Turning on the .pl Extension EverywhereThe previous technique specifies a specific directory for the Perl scripts. If you wantany file with an extension of pl (regardless of the directory) considered as a Perlscript instead, the following Files directive can accomplish this:

<Files *.pl>SetHandler perl-scriptPerlHandler Apache::RegistryPerlSendHeader OnOptions +ExecCGI

</Files>

Turning on the Perl StatusIf you want to receive status information from the Perl module, you can uncommentthe following lines from the iAS configuration file:

<Location /perl-status>SetHandler perl-scriptPerlHandler Apache::Statusorder deny,allowdeny from allallow from localhost

</Location>

TIPThe perl-status virtual path previously shown is onlyallowed from the localhost. If you want to accessthis from other machines, you must add them to theallow list. For example, allow from localhost,tuscbdb, 192.168.0.2.

Running OWA from PerlApache::OWA makes it possible for you to run scripts written with the PL/SQLWeb Toolkit (htp, htf, owa_util, and so forth) under Apache. You can download theApache OWA module for PL/SQL from http://theoryx5.uwinnipeg.ca/mod_perl/cpan-search?dist=Apache-OWA-0.7 or simply search for Apache OWA in a searchengine like Google. This module uses Perl to access the Oracle database. Thefollowing Location directive defines a virtual path of /scott that uses the ApacheOWA module to connect to the ORCL system ID (SID) with a username of scott anda password of tiger:

P:\010Comp\Oracle8\388-3\Web1.vpThursday, October 04, 2001 12:36:55 PM

Color profile: Generic CMYK printer profileComposite Default screen

Page 7: Blind Folio ORACLE Series / Oracle9iWeb Development / Brown / 9388

Perl and the Perl Module

ORACLE Series / Oracle9i Web Development / Brown / 9388-3 / Web 1Blind Folio 1:7

<Location /scott/>SetHandler perl-scriptPerlHandler Apache::OWA;PerlSetVar DAD ORCL:scott:tiger

</Location>

Accessing Oracle from PerlOAS includes the DBI and DBD modules for Oracle. For some reason, Oracle leftthese modules (Apache::DBI, Perl DBI, and Perl DBD-Oracle) out of the iAS build.So, unfortunately, if you want to access Oracle (or other databases) from Perl, youneed to build, install, and test mod_Perl DBI/DBD-Oracle and Apache::DBI for youroperating system. For Windows NT or Windows 2000, follow these steps. You mustbe running Windows 2000 or Windows NT 4.0 with Service Pack 3. You also needa C compiler, such as Visual Studio version 5.0.

1. Verify Perl is in your system path and is set correctly, by clicking Start |Settings | Control Panel. In the Control Panel, double-click System. In theSystem dialog box, click the Environment tab. On the Environment page,scroll down the System Variables list and select Path. In the Value field atthe bottom of the page, add the Apache Perl path to the system path. Forexample, add the following to the beginning of system path: %ORACLE_HOME%\Apache\Perl\5.00503\bin\MSWin32-x86. Click Set and OK toclose the System dialog box.

2. Modify config.pm in the directory %ORACLE_HOME%\Apache\Perl\5.00503\lib\MSWin32-x86 to pick up the correct version of Perl. First,replace “c:\perl\” with “%ORACLE_HOME%\Apache\Perl\” everywhereapplicable. This includes entries such as prefix, prefixexp, and so forth.Next, replace libpth=“\lib” with libpth=“%ORACLE_HOME%\Apache\Perl\5.00503\lib %ORACLE_HOME%\Apache\Perl\site\5.00503\lib ...”

3. Build, test, and install DBI version 1.13. First, download DBI-1_13_tar.gzinto %ORACLE_HOME%\Apache (for example, into a directory namedDBI-1.13), and then unpack it. Next, go to the DBI-1.13 directory and run‘perl Makefile.PL’. Follow the README instructions carefully. Now, run‘nmake’. Next, run ‘nmake test’ and verify the test results. Then, run ‘nmakeinstall’ and make sure DBI is installed in the %ORACLE_HOME%\Apache\Perl\ directory.

4. Build, test, and install DBD-Oracle version 1.03. The DBD-Oracle moduleexpects enough Oracle software to be available to build the driversuccessfully. First, download DBD-Oracle-1_03_tar.gz into %ORACLE_HOME%\Apache (for example, into a directory named DBD-Oracle1.03)

P:\010Comp\Oracle8\388-3\Web1.vpThursday, October 04, 2001 12:36:55 PM

Color profile: Generic CMYK printer profileComposite Default screen

Page 8: Blind Folio ORACLE Series / Oracle9iWeb Development / Brown / 9388

Oracle9i Web Development

ORACLE Series / Oracle9i Web Development / Brown / 9388-3 / Web 1Blind Folio 1:8

and unpack it. Next, go to the DBD-Oracle1.03 directory and modifyMakefile.PL to reflect the correct OCIDIR. In particular, set $OCIDIR =“oci”; if it wasn’t set originally. Next, set the ORACLE_HOME environmentvariable to point to a valid iAS install or an Oracle 8.1.7 database install.Now, set the ORACLE_SID environment variable to point to a valid OracleSID. Then, follow the README instructions carefully. Next, run ‘perlMakefile.PL’. Then, run ‘nmake’, ‘nmake test’, and ‘nmake install’.

5. Build, test, and install Apache::DBI version 0.87. First, downloadApacheDBI-0_87_tar.tar into %ORACLE_HOME%\Apache (for example,into a directory named ApacheDBI-0.87) and unpack it. Follow theREADME instructions carefully. Next, run ‘perl Makefile.PL’. Then, run‘nmake’, ‘nmake test’, and ‘nmake install’.

6. Add the following line to your httpd.conf file:

PerlRequire <absolute path of Apache::DBI’s startup.pl script>

7. Modify the startup.pl connect call to:

Apache::DBI->connect_on_init(

“dbi:Oracle:tnsconnect”,

“username”,

“password”);

8. Restart iAS.

Accessing Oracle After Installing DBI and DBD-OracleTest the previous installation with the following Perl script:

use DBI;print “Content-type: text/plain\n\n”;

$dbh = DBI->connect(“dbi:Oracle:sales”, “scott”, “tiger”) ||die $DBI::errstr;

$stmt = $dbh->prepare(“select * from emp order by empno”) ||die $DBI::errstr;$rc = $stmt->execute() or die $DBI::errstr;while (($empno, $name) = $stmt->fetchrow()) {

print “$empno $name\n”; }warn $DBI::errstr if $DBI::err;die “fetch error: ” . $DBI::errstr if $DBI::err;$stmt->finish() or die “can’t close cursor”;$dbh->disconnect() or die “can’t log off Oracle”

P:\010Comp\Oracle8\388-3\Web1.vpThursday, October 04, 2001 12:36:55 PM

Color profile: Generic CMYK printer profileComposite Default screen

Page 9: Blind Folio ORACLE Series / Oracle9iWeb Development / Brown / 9388

Perl and the Perl Module

If the previous script is placed into the /perl directory (as previously defined) andinto a file called emp.pl, you would execute the previous script from your browseras follows:

http://localhost/perl/emp.pl

Learning More About the Perl DatabaseInterface ModuleDBI is effectively what JDBC is to Java and ODBC is to Microsoft. You can learnabout DBI at http://www.perl.com/pub/1999/10/DBI.html. This page provides ashort guide to DBI and also includes examples of DBI code to access an Oracledatabase.

DBD Interfaces AvailableBeyond Oracle, you might wonder what databases Perl has access to. The followingtable contains a list of the databases supported by Perl DBD interfaces (note, this listcontinues to change).

DBD Module Database Supported by JDBC?

ASAny Adaptive Server Anywhere Database No

Adabas Adabas D Database Yes

CSV CSV files Yes

Chart Abstraction for DBD::Chart::Plot andGD::Graph (for rendering pie charts,bar charts, and line and point graphs)

No

DB2 IBM’s DB2 Database Yes

DBMaker DBMAKER Database Yes

DtfSQLmac dtF/SQL 2.01 database (for theMacintosh)

No

Empress Empress databases Yes

Excel Excel 95, 97, and 2000 Files No

FreeTDS Microsoft SQLServer and Sybasethrough raw TDS protocol

Yes

Fullcrum Fulcrum SearchServer No

Illustra Illustra database No

ORACLE Series / Oracle9i Web Development / Brown / 9388-3 / Chapter 1Blind Folio 1:9

P:\010Comp\Oracle8\388-3\Web1.vpThursday, October 04, 2001 12:36:56 PM

Color profile: Generic CMYK printer profileComposite Default screen

Page 10: Blind Folio ORACLE Series / Oracle9iWeb Development / Brown / 9388

Informix Informix database Yes

Ingres Ingres database Yes

InterBase InterBase RDBMS Server Yes

JDBC JDBC proxy driver Yes

mySQL mySQL database Yes

ODBC ODBC databases Yes

Oracle Oracle database Yes

Ovrimos Ovrimos database No

Pg PostgreSQL database Yes

Qbase QuickBase database No

RAM RAM database No

Solid SOLID database Yes

Sprite Flat Text Files Yes

SqlFlex SqlFlex database No

Sybase Sybase database Yes

Teradata Teradata database Yes

Unify Unify family of database products No

XBase XBase (dBase, Foxbase) database files,namely dbf, dbt, fpt, ndx, ntx

Yes

Testing and Debugging PerliAS doesn’t provide an easy way to debug your Perl scripts, so consider installinga standalone version of Perl to test your code outside iAS. You can download thestandard distribution of Perl for NT (Win32) from http://www.perl.com and theActivePerl distribution from http://www.activestate.com.

If you’re developing a considerable amount of Perl code, consider getting adebugging tool (a cryptic debugger is available under standard Perl). You mightalso want to consider purchasing a Perl debugger. ActiveState has developed a Perldebugger for the NT environment, along with a number of programs that enhancePerl. ActiveState’s Perl debugger enables you to debug Perl code visually byshowing watches, variables, and registers. The tool also makes it simple to jumpto statements, edit source, step through code, insert breakpoints, and so forth. Todebug any Perl script from the command line, add the debug mode parameter (-d).

Oracle9i Web Development

ORACLE Series / Oracle9i Web Development / Brown / 9388-3 / Web 1Blind Folio 1:10

P:\010Comp\Oracle8\388-3\Web1.vpThursday, October 04, 2001 12:36:56 PM

Color profile: Generic CMYK printer profileComposite Default screen

Page 11: Blind Folio ORACLE Series / Oracle9iWeb Development / Brown / 9388

Using a Standard CGI LibraryI recommend using a standard Perl CGI Library instead of writing your own routinesto obtain information from standard input (STDIN) and writing standard headersand other HTML output. Several such libraries are available on the Web. Whilethis might be debatable, two “de facto standard” CGI libraries exist. These librariesprovide a standard CGI library for GET/POST operations, writing the CGI headers,printing HTML tags, and much more.

One self-proclaimed de facto standard library is cgi-lib.pl, which can be foundat http://cgi-lib.berkeley.edu/. Steven Brenner, the author of cgi-lib.pl, coauthoreda book that covers CGI scripting and cgi-lib.pl. The book is CGI/Perl by Diane L.Zak (Course Technology, 2001). OAS previously came with a hack version calledmycgi-lib.pl, so if you have this around, you can still use this library. You candownload (actually cut-and-paste) the current cgi-lib from the previous site.Include this library in your Perl scripts as follows:

require “c:\websites\perl\cgi-lib.pl”;

The “real” standard CGI library, included into the official Perl build as ofPerl 5, is CGI.pm. CGI.pm is currently at version 2.752, and was developed byLincoln D. Stein ([email protected]). Documentation for this module can be foundat http://stein.cshl.org/WWW/software/CGI/. Lincoln wrote Official Guide toProgramming with CGI.pm (John Wiley, 1998). This book is well written and easyto read. The CGI.pm library is referenced as follows:

Use CGI;

CGI.pm contains an extremely extensive library of Web developmentcapabilities, so I highly recommend using it.

Displaying a List of FilesSay you want to display a directory listing the files on the Web server itself. Thefollowing example shows a Perl script that reads through a directory (that’s passedin or defaults to the root directory on the d: drive). This script uses the CGI librarypreviously described. The following script includes links that recursively callthemselves as the user drills into the directory listings:

# Dirlist.pl# Include the standard cgi library that comes with Application Serverrequire “c:\websites\perl\cgi-lib.pl”;

# Read in all the variables set by the form

Perl and the Perl Module

ORACLE Series / Oracle9i Web Development / Brown / 9388-3 / Web 1Blind Folio 1:11

P:\010Comp\Oracle8\388-3\Web1.vpThursday, October 04, 2001 12:36:56 PM

Color profile: Generic CMYK printer profileComposite Default screen

Page 12: Blind Folio ORACLE Series / Oracle9iWeb Development / Brown / 9388

&ReadParse(*input);

# Print the HTTP header (Content-type: text/html)print &PrintHeader;

# Get the directory passed in$dir = $in{“dir”};

# If no directory ($dir) was received,# set it to the root directory on the d driveif ($dir eq “” || $dir eq “d:/”) {

$dir = “d://”;$dir2 = $dir;chop($dir2);

}else {

$dir2 = $dir;}

# Start the HTML file off with the standard HTML tag, then the# HEAD tag. Put the window title up - that includes the# dynamic directory passed in

# Close the head and start the body.print “<html>”;print “<head>”;print “<title>Directory Listing on Server for Folder $dir</title>”;print “</head>”;print “<body>”;

# Print a header level 2 with the directory name# that we are currently reviewingprint “<h2>Folder $dir</h2>”;

# Set the flag to N(o) that we haven’t seen the table header yet.$flag = “N”;

# Open the directory that was set aboveopendir (DIR,$dir);

# Read the directory, sorting the file names and for each value# in the array returned, loop with a foreach loop

foreach $name (sort readdir(DIR)) {# If the table header flag is set to N(o), then we need to# start the table and print the headings# at the top of the table

if ($flag eq “N”) {print “<table border=1>”;print “<tr>”;

Oracle9i Web Development

ORACLE Series / Oracle9i Web Development / Brown / 9388-3 / Web 1Blind Folio 1:12

P:\010Comp\Oracle8\388-3\Web1.vpThursday, October 04, 2001 12:36:56 PM

Color profile: Generic CMYK printer profileComposite Default screen

Page 13: Blind Folio ORACLE Series / Oracle9iWeb Development / Brown / 9388

print “<td><b>Profile</b></td>”;print “<td><b>Created</b></td>”;print “<td><b>Operations</b></td>”;print “</tr>”;$flag = “Y”;

}

# Concatenate the directory and the file name (that we are working on)$file = $dir2 . $name;

# Collect each of the components about the file we are working with($dev,$inode,$perm,$hardl,$userid,$groupid,$devtype,$size,$atime,

$mtime,$sts,$block,$bsize) = stat($file);

# Convert the mtime (last modified time) to the localtime zone’s time($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =localtime($mtime);

# Since month is 0-11, need to add 1 to it for printing$mon++;

# Format the minutes to left pad with a 0$min = sprintf(“%02.0f”,$min);

# Start a new table row, print the modified date in a cellprint “<tr>”;print “<td>$name</td><td>$mon/$mday/$year $hour:$min</td>”;

# If the file size is 0, we are assuming this is a directory,# which in this case, print an anchor that allows the user to# drill into that directory. Then end the table row.if ($size eq “0" || $size eq ”") {

print “<td><a href=\”dirlist.pl?dir=$dir2$name\/\"" +“>Go to Folder</a>”;

};print “</tr>”;

}

# Close up the directoryclosedir(DIR);

# If the flag didn’t get set, if never saw a file# in the directory, then say soif ($flag eq “N”) {

print “<p><h3>There are no files in this folder $dir</h3></p>”;}

# End the HTML table, the body and the HTML file.print “</table>”;print “</body>”;print “</html>”;

Perl and the Perl Module

ORACLE Series / Oracle9i Web Development / Brown / 9388-3 / Web 1Blind Folio 1:13

P:\010Comp\Oracle8\388-3\Web1.vpThursday, October 04, 2001 12:36:57 PM

Color profile: Generic CMYK printer profileComposite Default screen

Page 14: Blind Folio ORACLE Series / Oracle9iWeb Development / Brown / 9388

Oracle9i Web Development

ORACLE Series / Oracle9i Web Development / Brown / 9388-3 / Web 1Blind Folio 1:14

Determining if a File ExistsTo determine whether an operating system flat file exists, use the following script.In this example, $filename is passed into the routine. If the file already exists, oneaction should be presented and, if it doesn’t exist, another action should be taken.

if(-T $filename) {# text file exists so take action hereprint “Text file ($filename) was found.”;

} else {# text file doesn’t exist so take another actionprint “Text file ($filename) was not found.”;

}

In the previous script, -T will return True if the file exists and is a text file. If thefile doesn’t exist, the message “Text file ($filename) was not found” is returned.

Creating or Appending a FileTo always create a new file (overwrite an existing file and create a new file), executethe following syntax:

open(FILE, “>$filename”) ||die(“Couldn’t open $filename for writing \n”);

To append to an existing file or to create a new file if the file doesn’t exist, thesyntax would be identical to the following:

open(FILE, “>>$filename”) || die(“Can’t append to $filename \n”);

In other words, when one greater-than symbol (>) precedes the filename, Perlwill open the file for writing, overwrite the existing file, and create a new file. Iftwo greater-than symbols (>>) precede the filename, Perl will append to the existingfile or create a new one if the file doesn’t exist. Opening the file with the less-thansymbol (<) or nothing, opens the file as read-only. The die clause traps run-timeerrors to control the flow and is very important in CGI programming. The desiredresult is a well-behaved routine that won’t abort with an unaccounted-for condition.Otherwise, you receive the Save As dialog box, as previously described.

Also, be aware of the process for an OS user to open the file. In other words, do usershave access rights to create/write to files? Remember, you’re running in a multithreadedenvironment and should ensure the filenames are unique or concurrency locked toprevent multiple writes happening at the same time to a single file. Opening a file inAppend mode doesn’t guarantee your data will be in the file if other processes canaccess or write to it while you think you’re writing to it.

P:\010Comp\Oracle8\388-3\Web1.vpThursday, October 04, 2001 12:36:57 PM

Color profile: Generic CMYK printer profileComposite Default screen

Page 15: Blind Folio ORACLE Series / Oracle9iWeb Development / Brown / 9388

Invoking a PL/SQL Procedurefrom PerlIf you have a Perl script that needs to access PL/SQL—or if you have a need toaccess any URL from Perl—this section explores the solution. For example, a Perlscript may exist that performs authentication and, if the entered data is valid, placesthe data in to your Oracle database. From PL/SQL, use the owa_util.redirect_url(new_location) command to branch to any other URL. This command outputs a“location: {new_location}” HTTP header. To call another URL instead of printing thecontent-type: header, use the location: header, as illustrated in the following syntax:

Print “location: $new_location?in_parameter=$form_parameter_1&in_parameter2=$in_parameter2\n\n”;

If you want to embed the results of the PL/SQL script in to your Perl output, you canaccomplish this by using the utl_http.request command, as described in Chapter 11.

Emulating a Browser from theCommand LineIf you experience difficulties debugging a Perl script from the browser, emulate abrowser from the server by setting the HTTP_USER_AGENT environment variablemanually. For example, for csh (C Shell):

setenv HTTP_USER_AGENT “Mozilla/4.05"

For ksh (Korne Shell):

export HTTP_USER_AGENT = “Mozilla/4.05"

Emulating a POST Request from theCommand LineIf the HTML form is passing the information to your Perl script through the POSTmethod, you can also emulate this functionality from the command line. Emulatea POST request by placing the data in a file and piping it to your Perl script, asillustrated in the following syntax:

cat mypost.file | my_perl_script.pl

Perl and the Perl Module

ORACLE Series / Oracle9i Web Development / Brown / 9388-3 / Web 1Blind Folio 1:15

P:\010Comp\Oracle8\388-3\Web1.vpThursday, October 04, 2001 12:36:57 PM

Color profile: Generic CMYK printer profileComposite Default screen

Page 16: Blind Folio ORACLE Series / Oracle9iWeb Development / Brown / 9388

Cleaning Up Your HTMLWhat if you have HTML code that was generated (FrontPage) or came from anothersource (Word, PowerPoint) and the HTML isn’t clean (in other words, it doesn’t followthe de facto standards of HTML development)? A great Perl script, Weblint, can beused for the express purpose of cleaning up HTML code. Weblint is available at

http://www.weblint.org/

This Perl script can be executed either through the Perl cartridge or from thecommand line. The output can be redirected and executed against a tree structureto evaluate more than one file.

Another tool, called the demoroniser (you have to love the name), performsa similar function. In the documentation, its stated purpose is as follows: “Thedemoroniser keeps you from looking dumber than a bag of dirt when your Webpage is viewed by a user on a non-Microsoft platform.” The author is John Walker,who founded AutoDesk and was the original author of AutoCAD. The demoroniserutility can be found at http://www.fourmilab.ch/webtools/demoroniser/.

The following are some errors the demoroniser fixes:

■ Missing semicolons at the end of numeric character escapes (&#061;)are supplied

■ Numeric renderings of special characters (&lt; &gt; &amp;) are replacedwith readable equivalents

■ Unquoted <table> tags containing nonalphanumeric characters are quoted

■ PowerPoint’s misnesting of <font> and <strong> tags is corrected

■ PowerPoint’s use of <ul> and </ul> tags to accomplish paragraph breaks iscorrected and the proper <p> tags are inserted

■ Missing <tr> tags in text-only slides are inserted

■ Nugatory </p> tags are removed

■ Unmatched <li> tags in headings are removed

■ Paragraph-long lines are broken into something suitable for editing with anormal text editor

Another good source for an HTML validator, which is more strict than Weblintcan be found at http://www.htmlhelp.com/tools/validator/source.html.

Weblint, which is Open Source with the Perl Artistic License, is useful andincludes a CSS validator and CGI test suite, found in the Tools section of the site.

Oracle9i Web Development

ORACLE Series / Oracle9i Web Development / Brown / 9388-3 / Web 1Blind Folio 1:16

P:\010Comp\Oracle8\388-3\Web1.vpThursday, October 04, 2001 12:36:58 PM

Color profile: Generic CMYK printer profileComposite Default screen

Page 17: Blind Folio ORACLE Series / Oracle9iWeb Development / Brown / 9388

Getting Access to Perl DocumentationThe Perl documentation is included with the Perl distribution. However,the complete Perl documentation can be found on the perl.com site athttp://www.perl.com/pub/v/documentation.

Additional tutorial information is available at http://www.perl.com/reference/query.cgi?tutorials.

Looking at theEnvironmental ParametersTo view all the environmental variables, Perl provides an associative array named%ENV. The following is a script segment that dumps out all the environmentvariables (sorted):

foreach $key (sort keys %ENV) {print $key, “ = ”, $ENV{$key}, “\n”;

}

The preceding code provides the same basic functionality as the owa_util.print_cgi_env packaged PL/SQL procedure.

Sending Mail from PerlSending electronic mail from a Perl script is actually easier than it might sound.The following code segment assumes you passed in the following variables:$from, $name, $to, $subject, and $message. The script uses Sendmail(http://www.Sendmail.org) to send the e-mail from the server:

open (SENDMAIL, “| c:\sendmail\sendmail.exe -t -n”);print SENDMAIL <<End_of_Mail;From: $from <$name>To: $toReply-To: $fromSubject: $subject$messageEnd_of_Mail

For additional sophistication, a Perl script called Formmail can be used tosimplify the process. Formmail is simple to work with and you can find it at http://www.worldwidemart.com/scripts/formmail.shtml.

Perl and the Perl Module

ORACLE Series / Oracle9i Web Development / Brown / 9388-3 / Web 1Blind Folio 1:17

P:\010Comp\Oracle8\388-3\Web1.vpThursday, October 04, 2001 12:36:58 PM

Color profile: Generic CMYK printer profileComposite Default screen

Page 18: Blind Folio ORACLE Series / Oracle9iWeb Development / Brown / 9388

Oracle9i Web Development

ORACLE Series / Oracle9i Web Development / Brown / 9388-3 / Web 1Blind Folio 1:18

Determining the Client Browserand Acting AccordinglyThe following segment of code queries the environmental variable containingspecific browser information. Using this information, your Perl script can adjust tothe browser accordingly.

$browser = $ENV{‘HTTP_USER_AGENT’};# the i switch makes the match case insensitiveif ($browser =~ /mozilla/i) {

# Netscape actions here} else {

# Non Netscape actions here}

Including Site ComponentsHave you ever wanted to include another HTML page (maybe a template or otherinformation) into your current page? Or include a snippet of information from anothersite into your current page? The libwww-perl library is the source of a number of suchutilities, such as WWW::Search, WebMirror, WebPluck, and WebFetch. These utilitiesand more can be found at http://www.linpro.no/lwp/.

Sample Code Accessing OracleThe following example will log on to a database, make a query, and display theoutput. This is a standard structure. Complete DBI and DBD documentation isavailable on the Web.

# Loads the DBI module. Loading the DBI module consists of# reading in the Perl module script (DBI.pm) and the shared# object (DBI.so). These files extend the Perl language by# defining calls that enable Perl scripts to connect to# Oracle databases. Once the module is loaded, the shared# object is dynamically linked with the cartridge, the# .pm Perl scripts are read in, compiled, and stored in# the package namespace. Scripts can then make calls defined# in the .pm file. The example calls the connect(), prepare(),# execute(), rows(), fetchrow(), finish(), and disconnect()# methods in the DBI module.use DBI;

# Prints the HTTP header for this HTML pageprint “Content-type: text/plain\n\n”;

P:\010Comp\Oracle8\388-3\Web1.vpThursday, October 04, 2001 12:36:58 PM

Color profile: Generic CMYK printer profileComposite Default screen

Page 19: Blind Folio ORACLE Series / Oracle9iWeb Development / Brown / 9388

Perl and the Perl Module

ORACLE Series / Oracle9i Web Development / Brown / 9388-3 / Web 1Blind Folio 1:19

# Logs into the Oracle database using SQL*Net connect string# of sales.$dbh = DBI->connect(“dbi:Oracle:sales”, “scott”, “tiger”) or

die $DBI::errstr;

# Prepares the SQL statement (parses the cursor)$stmt = $dbh->prepare(“select * from emp order by empno”) or

die $DBI::errstr;

# Executes the above SQL statement$rc = $stmt->execute() or die $DBI::errstr;

# Retrieve the number of fields returned from the above statement$nfields = $stmt->rows();

# Prints a message to the user, showing how many fields can bereturned print “Query will return up to $nfields fields\n\n”;

# Each relative column (field) returned from the SQL statement are# placed into each of the relative field names in the while statement.# In other words, the first field is placed into a variable called# $empno and the second is placed into a field called $name.while (($empno, $name) = $stmt->fetchrow()) { print “$empno $name\n”; }

# Display error messages if we get an errorwarn $DBI::errstr if $DBI::err;die “fetch error: ” . $DBI::errstr if $DBI::err;

# Close up the cursor and disconnect from the DB$stmt->finish() or die “can’t close cursor”;$dbh->disconnect() or die “can’t log off Oracle”;

Perl Startup FileBy using the Perl require directive, you can specify a Perl script that will stay loaded forevery user. In other words, the Perl require directive is a startup or initialization scriptfor Perl. For example, if you include the following directive in the iAS configuration file(httpd.conf), a script called startup.pl is executed on the startup of iAS:

Perlrequire /perl/startup.pl

The following is an example of what startup.pl might look like to load up theDBI module and DBD for Oracle at iAS startup:

# Requires that all variables be declared (should always use this)use strict;use Apache::Registry;

P:\010Comp\Oracle8\388-3\Web1.vpThursday, October 04, 2001 12:36:58 PM

Color profile: Generic CMYK printer profileComposite Default screen

Page 20: Blind Folio ORACLE Series / Oracle9iWeb Development / Brown / 9388

Oracle9i Web Development

ORACLE Series / Oracle9i Web Development / Brown / 9388-3 / Web 1Blind Folio 1:20

# Standard CGI library as discussed aboveuse CGI;# Part of standard CGI library, primarily for error formattinguse CGI::Carp;# Include the DBI (database interface) moduleuse DBI;1;

Making DatabaseConnections PersistentTo change the previous example so it preloads the DBI module and logs in to thedatabase, thus making the connection to the Oracle database persistent, you needto define a “package” (or grouping of code) in the startup.pl file. The previousstartup.pl file would change as follows:

use strict;use Apache::Registry;use CGI;use CGI::Carp;package Scott;

# Setup for calling the Oracle databaseuse DBI;

# Logs into the Oracle database using SQL*Net connect string# of sales.$dbh = DBI->connect(“dbi:Oracle:sales”, “scott”, “tiger”) or

die $DBI::errstr;;1;

The preceding script would be modified to appear identical to the followingexample.

package Scott;

# Prints the HTTP header for this HTML pageprint “Content-type: text/plain\n\n”;

# Prepares the SQL statement (parses the cursor)$stmt = $dbh->prepare(“select * from emp order by empno”) or

die $DBI::errstr;

# Executes the above SQL statement$rc = $stmt->execute() or die $DBI::errstr;

P:\010Comp\Oracle8\388-3\Web1.vpThursday, October 04, 2001 12:36:59 PM

Color profile: Generic CMYK printer profileComposite Default screen

Page 21: Blind Folio ORACLE Series / Oracle9iWeb Development / Brown / 9388

Perl and the Perl Module

ORACLE Series / Oracle9i Web Development / Brown / 9388-3 / Web 1Blind Folio 1:21

# Retrieve the number of fields returned from the above statement$nfields = $stmt->rows();

# Prints a message to the user, showing how many fields can be returnedprint “Query will return up to $nfields fields\n\n”;

# Each relative column (field) returned from the SQL statement are# placed into each of the relative field names in the while statement.# In other words, the first field is placed into a variable called# $empno and the second is placed into a field called $name.while (($empno, $name) = $stmt->fetchrow()) { print “$empno $name\n”; }

# Display error messages if we get an errorwarn $DBI::errstr if $DBI::err;die “fetch error: ” . $DBI::errstr if $DBI::err;

# Close up the cursor and disconnect from the DB$stmt->finish() or die “can’t close cursor”;

The logging on and off functions, and the use of OraPerl statements, aren’tneeded in the scripts any more.

Reviewing Production OraPerl CodeSeeing a short example of code to gain an understanding of how the code appearsis nice, but it’s more effective to look at production code for a comprehensiveexample. The following code uses Perl as a CGI with DBI and DBD:Oraclecompiled into the Perl code:

#Set up to use DBI and DBDuse DBI;use DBI::DBD;

$dbh = DBI->connect(‘dbi:Oracle:sales’,$vcd_user, $vcd_password) ordie “Unable to connect to Oracle: $DBI::errstr”;

$test = length($key);

if ($test == 1){$csr = $dbh->prepare(“

SELECT DESCRP,COMMON_NAME,BOTANICAL_NAME,LOCATION,HARV_BLOOM_PER,CHEMICAL_CONTROL,ORGANIC_CONTROL,CULTURAL_CONTROL,MED_FILE,

P:\010Comp\Oracle8\388-3\Web1.vpThursday, October 04, 2001 12:36:59 PM

Color profile: Generic CMYK printer profileComposite Default screen

Page 22: Blind Folio ORACLE Series / Oracle9iWeb Development / Brown / 9388

SOURCEFROM tx_plantsWHERE (UPPER(COMMON_NAME) like ‘$key%’OR UPPER(BOTANICAL_NAME) like ‘$key%’)AND gard_type = ‘WEED’AND UPPER(BOTANICAL_NAME) > UPPER(‘$last’)ORDER BY BOTANICAL_NAME

”);}else{

$csr = $dbh->prepare(“SELECT DESCRP,COMMON_NAME,BOTANICAL_NAME,LOCATION,HARV_BLOOM_PER,CHEMICAL_CONTROL,ORGANIC_CONTROL,CULTURAL_CONTROL,MED_FILE,SOURCE

FROM tx_plantsWHERE (UPPER(COMMON_NAME) like ‘%$key%’OR UPPER(BOTANICAL_NAME) like ‘%$key%’)AND gard_type = ‘WEED’AND UPPER(BOTANICAL_NAME) > UPPER(‘$last’)ORDER BY BOTANICAL_NAME

”);}

$count = 0;

if ( defined $csr ) {$csr->execute;while ((( $descrp, $common_name, $botanical_name, $location, $harv_bloom,

$chemical_control, $organic_control, $cultural_control,$med_file, $source ) = $csr->fetchrow())&& ($count < 20){

$count++;$last = $botanical_name;

print <<“DETAIL1"<TR>

DETAIL1

$med_test = length $med_file;if ($med_test > 0) {

print <<”DETAIL2"<TD VALIGN="TOP"><IMG SRC=$med_file WIDTH="120"

HEIGHT="120" ALIGN="BOTTOM" BORDER="0"></TD>DETAIL2

}else{

Oracle9i Web Development

ORACLE Series / Oracle9i Web Development / Brown / 9388-3 / Web 1Blind Folio 1:22

P:\010Comp\Oracle8\388-3\Web1.vpThursday, October 04, 2001 12:36:59 PM

Color profile: Generic CMYK printer profileComposite Default screen

Page 23: Blind Folio ORACLE Series / Oracle9iWeb Development / Brown / 9388

print <<“DETAIL3"<TD VALIGN=”TOP" WIDTH="120" ALIGN="BOTTOM" BORDER="0"></TD>

DETAIL3

}

print <<“DETAIL4"<TD WIDTH=”120" VALIGN="TOP"><B>Common Name:</B></TD><TD WIDTH="296" VALIGN="TOP"><B><FONT SIZE="5"FACE="Helvetica, arial">$common_name</FONT></B></TD>

</TR><TR>

<TD VALIGN="TOP" WIDTH="120" ALIGN="BOTTOM" BORDER="0"></TD><TD WIDTH="120" VALIGN="TOP"><B>Scientific Name:</B></TD><TD WIDTH="296">$botanical_name</TD></TR><TR><TD VALIGN="TOP" WIDTH="120" ALIGN="BOTTOM" BORDER="0"></TD><TD WIDTH="120" VALIGN="TOP"><B>Description</B></TD><TD WIDTH="296">$descrp</TD></TR><TR><TD VALIGN="TOP" WIDTH="120" ALIGN="BOTTOM" BORDER="0"></TD><TD WIDTH="120" VALIGN="TOP"><B>Location:</B></TD><TD WIDTH="296">$location</TD></TR><TR><TD VALIGN="TOP" WIDTH="120" ALIGN="BOTTOM" BORDER="0"></TD><TD WIDTH="120" VALIGN="TOP"><B>Life Cycle:</B></TD><TD WIDTH="296">$harv_bloom</TD></TR><TR><TD VALIGN="TOP" WIDTH="120" ALIGN="BOTTOM" BORDER="0"></TD><TD WIDTH="120" VALIGN="TOP"><B>Organic Control:</B></TD><TD WIDTH="296">$organic_control</TD></TR><TR><TD VALIGN="TOP" WIDTH="120" ALIGN="BOTTOM" BORDER="0"></TD><TD WIDTH="120" VALIGN="TOP"><B>Cultural Control:</B></TD><TD WIDTH="296">$cultural_control</TD></TR><TR><TD VALIGN="TOP" WIDTH="120" ALIGN="BOTTOM" BORDER="0"></TD><TD WIDTH="120" VALIGN="TOP"><B>Chemical Control:</B></TD><TD WIDTH="296">$chemical_control</TD></TR><TR><TD VALIGN="TOP" WIDTH="120" ALIGN="BOTTOM" BORDER="0"></TD><TD WIDTH="120" VALIGN="TOP"><B>Where to Buy:</B></TD><TD WIDTH="296"><A HREF="../supply/supply.htm"

target="_parent">$source</A></TD>

Perl and the Perl Module

ORACLE Series / Oracle9i Web Development / Brown / 9388-3 / Web 1Blind Folio 1:23

P:\010Comp\Oracle8\388-3\Web1.vpThursday, October 04, 2001 12:36:59 PM

Color profile: Generic CMYK printer profileComposite Default screen

Page 24: Blind Folio ORACLE Series / Oracle9iWeb Development / Brown / 9388

Oracle9i Web Development

ORACLE Series / Oracle9i Web Development / Brown / 9388-3 / Web 1Blind Folio 1:24

</TR>DETAIL4

}$csr->finish;

}

$dbh->disconnect;

Example with a Procedure CallThe following code will log in to the database and execute a procedure called get_journal_note:

use DBI;use DBI::DBD;

$desc;$ret_error;

$dbh = DBI->connect(‘dbi:Oracle:sales’,$vcd_user, $vcd_password) or die“Unable to connect to Oracle:$DBI::errstr”;

$dbh->{RaiseError} = 1; # “off” by default; when set to “on”, any# method that results in an error will cause the DBI to effectively do a# die(“$class $method failed: $DBI::errstr”), where $class is the driver# class, and $method is the name of the method that failed$csr = $dbh->prepare(q{

BEGINGET_JOURNAL_NOTE(:name,:desc, :ret_error);

END;});

$csr->bind_param(“:name”,$key);$csr->bind_param_inout(“:desc”,\$desc, 500);$csr->bind_param_inout(“:ret_error”,\$ret_error, 1500);

$csr->execute;$error_out = $ret_error;$dbh->disconnect;

SummaryPerl is a powerful tool for programming robust, dynamic Web applications. It is anexcellent way to make otherwise static HTML documents “come alive.” When usedwith iAS, Perl is best for accessing other databases, file system read/write activity,and running operating system programs. Another great advantage of Perl is the

P:\010Comp\Oracle8\388-3\Web1.vpThursday, October 04, 2001 12:36:59 PM

Color profile: Generic CMYK printer profileComposite Default screen

Page 25: Blind Folio ORACLE Series / Oracle9iWeb Development / Brown / 9388

countless number of public domain Perl scripts available on the Web. (Thecommunity-supported scripts are located at http://www.perl.com/CPAN-local/README.html.)

Sites That Provide Perl Informationftp://ftp.cis.ufl.edu/pub/perl University of Florida; largest FTP site

for Perl interpreter and Perl scripts

http://www.perl.com Perl site maintained by TomChristiansen with over 14,000 files andover 300MB of Perl information

http://www.perl.org Perl Institutes site dedicated to makingPerl more useful

http://www.oasis.leo.org An extensive archive of Perl scripts,extensions, documentation, platform-specific issues, and so forth

http://www.worldwidemart.com/scripts

A good collection of scripts that dogeneric tasks (Matt Wright’s Web siteis fun to visit)

http://www.stars.com Wal-Mart of Web development

http://www.perl.com/cgi-bin/cpan_mod?module=dbd::oracle

To download DBD for Oracle

http://post.sunyit.edu/perl5/ Perl 5 on NT documentation

http://www.symbolstone.org/technology/perl/DBI/index.html

Perl and DBD

http://www.apache.org/httpd.html Apache home page

http://www.oasis.leo.org/cgi-bin/search-perl

Perl search site

http://www.activestate.com Download Perl for Win32

http://www.4images.com/ntperl/ Perl on NT hints, tips, and techniques

Perl and the Perl Module

ORACLE Series / Oracle9i Web Development / Brown / 9388-3 / Web 1Blind Folio 1:25

P:\010Comp\Oracle8\388-3\Web1.vpThursday, October 04, 2001 12:36:59 PM

Color profile: Generic CMYK printer profileComposite Default screen