xref: /onnv-gate/usr/src/cmd/perl/5.8.4/distrib/lib/CGI.pm (revision 6287:9a1f5d2c8dd8)
10Sstevel@tonic-gatepackage CGI;
20Sstevel@tonic-gaterequire 5.004;
30Sstevel@tonic-gateuse Carp 'croak';
40Sstevel@tonic-gate
50Sstevel@tonic-gate# See the bottom of this file for the POD documentation.  Search for the
60Sstevel@tonic-gate# string '=head'.
70Sstevel@tonic-gate
80Sstevel@tonic-gate# You can run this file through either pod2man or pod2html to produce pretty
90Sstevel@tonic-gate# documentation in manual or html file format (these utilities are part of the
100Sstevel@tonic-gate# Perl 5 distribution).
110Sstevel@tonic-gate
120Sstevel@tonic-gate# Copyright 1995-1998 Lincoln D. Stein.  All rights reserved.
130Sstevel@tonic-gate# It may be used and modified freely, but I do request that this copyright
140Sstevel@tonic-gate# notice remain attached to the file.  You may modify this module as you
150Sstevel@tonic-gate# wish, but if you redistribute a modified version, please attach a note
160Sstevel@tonic-gate# listing the modifications you have made.
170Sstevel@tonic-gate
180Sstevel@tonic-gate# The most recent version and complete docs are available at:
190Sstevel@tonic-gate#   http://stein.cshl.org/WWW/software/CGI/
200Sstevel@tonic-gate
21*6287Sps156622$CGI::revision = '$Id: CGI.pm,v 1.241 2007/12/27 18:37:43 lstein Exp $';
22*6287Sps156622$CGI::VERSION='3.33';
230Sstevel@tonic-gate
240Sstevel@tonic-gate# HARD-CODED LOCATION FOR FILE UPLOAD TEMPORARY FILES.
250Sstevel@tonic-gate# UNCOMMENT THIS ONLY IF YOU KNOW WHAT YOU'RE DOING.
260Sstevel@tonic-gate# $CGITempFile::TMPDIRECTORY = '/usr/tmp';
270Sstevel@tonic-gateuse CGI::Util qw(rearrange make_attributes unescape escape expires ebcdic2ascii ascii2ebcdic);
280Sstevel@tonic-gate
290Sstevel@tonic-gate#use constant XHTML_DTD => ['-//W3C//DTD XHTML Basic 1.0//EN',
300Sstevel@tonic-gate#                           'http://www.w3.org/TR/xhtml-basic/xhtml-basic10.dtd'];
310Sstevel@tonic-gate
320Sstevel@tonic-gateuse constant XHTML_DTD => ['-//W3C//DTD XHTML 1.0 Transitional//EN',
330Sstevel@tonic-gate                           'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'];
340Sstevel@tonic-gate
350Sstevel@tonic-gate{
360Sstevel@tonic-gate  local $^W = 0;
370Sstevel@tonic-gate  $TAINTED = substr("$0$^X",0,0);
380Sstevel@tonic-gate}
390Sstevel@tonic-gate
400Sstevel@tonic-gate$MOD_PERL = 0; # no mod_perl by default
41667Sps156622@SAVED_SYMBOLS = ();
420Sstevel@tonic-gate
43*6287Sps156622
440Sstevel@tonic-gate# >>>>> Here are some globals that you might want to adjust <<<<<<
450Sstevel@tonic-gatesub initialize_globals {
460Sstevel@tonic-gate    # Set this to 1 to enable copious autoloader debugging messages
470Sstevel@tonic-gate    $AUTOLOAD_DEBUG = 0;
480Sstevel@tonic-gate
490Sstevel@tonic-gate    # Set this to 1 to generate XTML-compatible output
500Sstevel@tonic-gate    $XHTML = 1;
510Sstevel@tonic-gate
520Sstevel@tonic-gate    # Change this to the preferred DTD to print in start_html()
530Sstevel@tonic-gate    # or use default_dtd('text of DTD to use');
540Sstevel@tonic-gate    $DEFAULT_DTD = [ '-//W3C//DTD HTML 4.01 Transitional//EN',
550Sstevel@tonic-gate		     'http://www.w3.org/TR/html4/loose.dtd' ] ;
560Sstevel@tonic-gate
570Sstevel@tonic-gate    # Set this to 1 to enable NOSTICKY scripts
580Sstevel@tonic-gate    # or:
590Sstevel@tonic-gate    #    1) use CGI qw(-nosticky)
600Sstevel@tonic-gate    #    2) $CGI::nosticky(1)
610Sstevel@tonic-gate    $NOSTICKY = 0;
620Sstevel@tonic-gate
630Sstevel@tonic-gate    # Set this to 1 to enable NPH scripts
640Sstevel@tonic-gate    # or:
650Sstevel@tonic-gate    #    1) use CGI qw(-nph)
660Sstevel@tonic-gate    #    2) CGI::nph(1)
670Sstevel@tonic-gate    #    3) print header(-nph=>1)
680Sstevel@tonic-gate    $NPH = 0;
690Sstevel@tonic-gate
700Sstevel@tonic-gate    # Set this to 1 to enable debugging from @ARGV
710Sstevel@tonic-gate    # Set to 2 to enable debugging from STDIN
720Sstevel@tonic-gate    $DEBUG = 1;
730Sstevel@tonic-gate
740Sstevel@tonic-gate    # Set this to 1 to make the temporary files created
750Sstevel@tonic-gate    # during file uploads safe from prying eyes
760Sstevel@tonic-gate    # or do...
770Sstevel@tonic-gate    #    1) use CGI qw(:private_tempfiles)
780Sstevel@tonic-gate    #    2) CGI::private_tempfiles(1);
790Sstevel@tonic-gate    $PRIVATE_TEMPFILES = 0;
800Sstevel@tonic-gate
81*6287Sps156622    # Set this to 1 to generate automatic tab indexes
82*6287Sps156622    $TABINDEX = 0;
83*6287Sps156622
840Sstevel@tonic-gate    # Set this to 1 to cause files uploaded in multipart documents
850Sstevel@tonic-gate    # to be closed, instead of caching the file handle
860Sstevel@tonic-gate    # or:
870Sstevel@tonic-gate    #    1) use CGI qw(:close_upload_files)
880Sstevel@tonic-gate    #    2) $CGI::close_upload_files(1);
890Sstevel@tonic-gate    # Uploads with many files run out of file handles.
900Sstevel@tonic-gate    # Also, for performance, since the file is already on disk,
910Sstevel@tonic-gate    # it can just be renamed, instead of read and written.
920Sstevel@tonic-gate    $CLOSE_UPLOAD_FILES = 0;
930Sstevel@tonic-gate
940Sstevel@tonic-gate    # Set this to a positive value to limit the size of a POSTing
950Sstevel@tonic-gate    # to a certain number of bytes:
960Sstevel@tonic-gate    $POST_MAX = -1;
970Sstevel@tonic-gate
980Sstevel@tonic-gate    # Change this to 1 to disable uploads entirely:
990Sstevel@tonic-gate    $DISABLE_UPLOADS = 0;
1000Sstevel@tonic-gate
1010Sstevel@tonic-gate    # Automatically determined -- don't change
1020Sstevel@tonic-gate    $EBCDIC = 0;
1030Sstevel@tonic-gate
1040Sstevel@tonic-gate    # Change this to 1 to suppress redundant HTTP headers
1050Sstevel@tonic-gate    $HEADERS_ONCE = 0;
1060Sstevel@tonic-gate
1070Sstevel@tonic-gate    # separate the name=value pairs by semicolons rather than ampersands
1080Sstevel@tonic-gate    $USE_PARAM_SEMICOLONS = 1;
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate    # Do not include undefined params parsed from query string
1110Sstevel@tonic-gate    # use CGI qw(-no_undef_params);
1120Sstevel@tonic-gate    $NO_UNDEF_PARAMS = 0;
1130Sstevel@tonic-gate
114*6287Sps156622    # return everything as utf-8
115*6287Sps156622    $PARAM_UTF8      = 0;
116*6287Sps156622
1170Sstevel@tonic-gate    # Other globals that you shouldn't worry about.
1180Sstevel@tonic-gate    undef $Q;
1190Sstevel@tonic-gate    $BEEN_THERE = 0;
120667Sps156622    $DTD_PUBLIC_IDENTIFIER = "";
1210Sstevel@tonic-gate    undef @QUERY_PARAM;
1220Sstevel@tonic-gate    undef %EXPORT;
1230Sstevel@tonic-gate    undef $QUERY_CHARSET;
1240Sstevel@tonic-gate    undef %QUERY_FIELDNAMES;
125*6287Sps156622    undef %QUERY_TMPFILES;
1260Sstevel@tonic-gate
1270Sstevel@tonic-gate    # prevent complaints by mod_perl
1280Sstevel@tonic-gate    1;
1290Sstevel@tonic-gate}
1300Sstevel@tonic-gate
1310Sstevel@tonic-gate# ------------------ START OF THE LIBRARY ------------
1320Sstevel@tonic-gate
133667Sps156622*end_form = \&endform;
134667Sps156622
1350Sstevel@tonic-gate# make mod_perlhappy
1360Sstevel@tonic-gateinitialize_globals();
1370Sstevel@tonic-gate
1380Sstevel@tonic-gate# FIGURE OUT THE OS WE'RE RUNNING UNDER
1390Sstevel@tonic-gate# Some systems support the $^O variable.  If not
1400Sstevel@tonic-gate# available then require() the Config library
1410Sstevel@tonic-gateunless ($OS) {
1420Sstevel@tonic-gate    unless ($OS = $^O) {
1430Sstevel@tonic-gate	require Config;
1440Sstevel@tonic-gate	$OS = $Config::Config{'osname'};
1450Sstevel@tonic-gate    }
1460Sstevel@tonic-gate}
1470Sstevel@tonic-gateif ($OS =~ /^MSWin/i) {
1480Sstevel@tonic-gate  $OS = 'WINDOWS';
1490Sstevel@tonic-gate} elsif ($OS =~ /^VMS/i) {
1500Sstevel@tonic-gate  $OS = 'VMS';
1510Sstevel@tonic-gate} elsif ($OS =~ /^dos/i) {
1520Sstevel@tonic-gate  $OS = 'DOS';
1530Sstevel@tonic-gate} elsif ($OS =~ /^MacOS/i) {
1540Sstevel@tonic-gate    $OS = 'MACINTOSH';
1550Sstevel@tonic-gate} elsif ($OS =~ /^os2/i) {
1560Sstevel@tonic-gate    $OS = 'OS2';
1570Sstevel@tonic-gate} elsif ($OS =~ /^epoc/i) {
1580Sstevel@tonic-gate    $OS = 'EPOC';
1590Sstevel@tonic-gate} elsif ($OS =~ /^cygwin/i) {
1600Sstevel@tonic-gate    $OS = 'CYGWIN';
1610Sstevel@tonic-gate} else {
1620Sstevel@tonic-gate    $OS = 'UNIX';
1630Sstevel@tonic-gate}
1640Sstevel@tonic-gate
1650Sstevel@tonic-gate# Some OS logic.  Binary mode enabled on DOS, NT and VMS
1660Sstevel@tonic-gate$needs_binmode = $OS=~/^(WINDOWS|DOS|OS2|MSWin|CYGWIN)/;
1670Sstevel@tonic-gate
1680Sstevel@tonic-gate# This is the default class for the CGI object to use when all else fails.
1690Sstevel@tonic-gate$DefaultClass = 'CGI' unless defined $CGI::DefaultClass;
1700Sstevel@tonic-gate
1710Sstevel@tonic-gate# This is where to look for autoloaded routines.
1720Sstevel@tonic-gate$AutoloadClass = $DefaultClass unless defined $CGI::AutoloadClass;
1730Sstevel@tonic-gate
1740Sstevel@tonic-gate# The path separator is a slash, backslash or semicolon, depending
1750Sstevel@tonic-gate# on the paltform.
1760Sstevel@tonic-gate$SL = {
1770Sstevel@tonic-gate     UNIX    => '/',  OS2 => '\\', EPOC      => '/', CYGWIN => '/',
1780Sstevel@tonic-gate     WINDOWS => '\\', DOS => '\\', MACINTOSH => ':', VMS    => '/'
1790Sstevel@tonic-gate    }->{$OS};
1800Sstevel@tonic-gate
1810Sstevel@tonic-gate# This no longer seems to be necessary
1820Sstevel@tonic-gate# Turn on NPH scripts by default when running under IIS server!
1830Sstevel@tonic-gate# $NPH++ if defined($ENV{'SERVER_SOFTWARE'}) && $ENV{'SERVER_SOFTWARE'}=~/IIS/;
1840Sstevel@tonic-gate$IIS++ if defined($ENV{'SERVER_SOFTWARE'}) && $ENV{'SERVER_SOFTWARE'}=~/IIS/;
1850Sstevel@tonic-gate
1860Sstevel@tonic-gate# Turn on special checking for Doug MacEachern's modperl
1870Sstevel@tonic-gateif (exists $ENV{MOD_PERL}) {
1880Sstevel@tonic-gate  # mod_perl handlers may run system() on scripts using CGI.pm;
1890Sstevel@tonic-gate  # Make sure so we don't get fooled by inherited $ENV{MOD_PERL}
190667Sps156622  if (exists $ENV{MOD_PERL_API_VERSION} && $ENV{MOD_PERL_API_VERSION} == 2) {
191667Sps156622    $MOD_PERL = 2;
192667Sps156622    require Apache2::Response;
193667Sps156622    require Apache2::RequestRec;
194667Sps156622    require Apache2::RequestUtil;
195667Sps156622    require Apache2::RequestIO;
196667Sps156622    require APR::Pool;
197667Sps156622  } else {
198667Sps156622    $MOD_PERL = 1;
199667Sps156622    require Apache;
2000Sstevel@tonic-gate  }
2010Sstevel@tonic-gate}
2020Sstevel@tonic-gate
2030Sstevel@tonic-gate# Turn on special checking for ActiveState's PerlEx
2040Sstevel@tonic-gate$PERLEX++ if defined($ENV{'GATEWAY_INTERFACE'}) && $ENV{'GATEWAY_INTERFACE'} =~ /^CGI-PerlEx/;
2050Sstevel@tonic-gate
2060Sstevel@tonic-gate# Define the CRLF sequence.  I can't use a simple "\r\n" because the meaning
2070Sstevel@tonic-gate# of "\n" is different on different OS's (sometimes it generates CRLF, sometimes LF
2080Sstevel@tonic-gate# and sometimes CR).  The most popular VMS web server
2090Sstevel@tonic-gate# doesn't accept CRLF -- instead it wants a LR.  EBCDIC machines don't
2100Sstevel@tonic-gate# use ASCII, so \015\012 means something different.  I find this all
2110Sstevel@tonic-gate# really annoying.
2120Sstevel@tonic-gate$EBCDIC = "\t" ne "\011";
2130Sstevel@tonic-gateif ($OS eq 'VMS') {
2140Sstevel@tonic-gate  $CRLF = "\n";
2150Sstevel@tonic-gate} elsif ($EBCDIC) {
2160Sstevel@tonic-gate  $CRLF= "\r\n";
2170Sstevel@tonic-gate} else {
2180Sstevel@tonic-gate  $CRLF = "\015\012";
2190Sstevel@tonic-gate}
2200Sstevel@tonic-gate
2210Sstevel@tonic-gateif ($needs_binmode) {
2220Sstevel@tonic-gate    $CGI::DefaultClass->binmode(\*main::STDOUT);
2230Sstevel@tonic-gate    $CGI::DefaultClass->binmode(\*main::STDIN);
2240Sstevel@tonic-gate    $CGI::DefaultClass->binmode(\*main::STDERR);
2250Sstevel@tonic-gate}
2260Sstevel@tonic-gate
2270Sstevel@tonic-gate%EXPORT_TAGS = (
2280Sstevel@tonic-gate		':html2'=>['h1'..'h6',qw/p br hr ol ul li dl dt dd menu code var strong em
2290Sstevel@tonic-gate			   tt u i b blockquote pre img a address cite samp dfn html head
2300Sstevel@tonic-gate			   base body Link nextid title meta kbd start_html end_html
2310Sstevel@tonic-gate			   input Select option comment charset escapeHTML/],
2320Sstevel@tonic-gate		':html3'=>[qw/div table caption th td TR Tr sup Sub strike applet Param
2330Sstevel@tonic-gate			   embed basefont style span layer ilayer font frameset frame script small big Area Map/],
2340Sstevel@tonic-gate                ':html4'=>[qw/abbr acronym bdo col colgroup del fieldset iframe
2350Sstevel@tonic-gate                            ins label legend noframes noscript object optgroup Q
2360Sstevel@tonic-gate                            thead tbody tfoot/],
2370Sstevel@tonic-gate		':netscape'=>[qw/blink fontsize center/],
2380Sstevel@tonic-gate		':form'=>[qw/textfield textarea filefield password_field hidden checkbox checkbox_group
2390Sstevel@tonic-gate			  submit reset defaults radio_group popup_menu button autoEscape
2400Sstevel@tonic-gate			  scrolling_list image_button start_form end_form startform endform
2410Sstevel@tonic-gate			  start_multipart_form end_multipart_form isindex tmpFileName uploadInfo URL_ENCODED MULTIPART/],
242667Sps156622		':cgi'=>[qw/param upload path_info path_translated request_uri url self_url script_name
243667Sps156622			 cookie Dump
2440Sstevel@tonic-gate			 raw_cookie request_method query_string Accept user_agent remote_host content_type
2450Sstevel@tonic-gate			 remote_addr referer server_name server_software server_port server_protocol virtual_port
2460Sstevel@tonic-gate			 virtual_host remote_ident auth_type http append
2470Sstevel@tonic-gate			 save_parameters restore_parameters param_fetch
2480Sstevel@tonic-gate			 remote_user user_name header redirect import_names put
2490Sstevel@tonic-gate			 Delete Delete_all url_param cgi_error/],
2500Sstevel@tonic-gate		':ssl' => [qw/https/],
2510Sstevel@tonic-gate		':cgi-lib' => [qw/ReadParse PrintHeader HtmlTop HtmlBot SplitParam Vars/],
2520Sstevel@tonic-gate		':html' => [qw/:html2 :html3 :html4 :netscape/],
2530Sstevel@tonic-gate		':standard' => [qw/:html2 :html3 :html4 :form :cgi/],
2540Sstevel@tonic-gate		':push' => [qw/multipart_init multipart_start multipart_end multipart_final/],
2550Sstevel@tonic-gate		':all' => [qw/:html2 :html3 :netscape :form :cgi :internal :html4/]
2560Sstevel@tonic-gate		);
2570Sstevel@tonic-gate
258667Sps156622# Custom 'can' method for both autoloaded and non-autoloaded subroutines.
259667Sps156622# Author: Cees Hek <cees@sitesuite.com.au>
260667Sps156622
261667Sps156622sub can {
262667Sps156622	my($class, $method) = @_;
263667Sps156622
264667Sps156622	# See if UNIVERSAL::can finds it.
265667Sps156622
266667Sps156622	if (my $func = $class -> SUPER::can($method) ){
267667Sps156622		return $func;
268667Sps156622	}
269667Sps156622
270667Sps156622	# Try to compile the function.
271667Sps156622
272667Sps156622	eval {
273667Sps156622		# _compile looks at $AUTOLOAD for the function name.
274667Sps156622
275667Sps156622		local $AUTOLOAD = join "::", $class, $method;
276667Sps156622		&_compile;
277667Sps156622	};
278667Sps156622
279667Sps156622	# Now that the function is loaded (if it exists)
280667Sps156622	# just use UNIVERSAL::can again to do the work.
281667Sps156622
282667Sps156622	return $class -> SUPER::can($method);
283667Sps156622}
284667Sps156622
2850Sstevel@tonic-gate# to import symbols into caller
2860Sstevel@tonic-gatesub import {
2870Sstevel@tonic-gate    my $self = shift;
2880Sstevel@tonic-gate
2890Sstevel@tonic-gate    # This causes modules to clash.
2900Sstevel@tonic-gate    undef %EXPORT_OK;
2910Sstevel@tonic-gate    undef %EXPORT;
2920Sstevel@tonic-gate
2930Sstevel@tonic-gate    $self->_setup_symbols(@_);
2940Sstevel@tonic-gate    my ($callpack, $callfile, $callline) = caller;
2950Sstevel@tonic-gate
2960Sstevel@tonic-gate    # To allow overriding, search through the packages
2970Sstevel@tonic-gate    # Till we find one in which the correct subroutine is defined.
2980Sstevel@tonic-gate    my @packages = ($self,@{"$self\:\:ISA"});
2990Sstevel@tonic-gate    foreach $sym (keys %EXPORT) {
3000Sstevel@tonic-gate	my $pck;
3010Sstevel@tonic-gate	my $def = ${"$self\:\:AutoloadClass"} || $DefaultClass;
3020Sstevel@tonic-gate	foreach $pck (@packages) {
3030Sstevel@tonic-gate	    if (defined(&{"$pck\:\:$sym"})) {
3040Sstevel@tonic-gate		$def = $pck;
3050Sstevel@tonic-gate		last;
3060Sstevel@tonic-gate	    }
3070Sstevel@tonic-gate	}
3080Sstevel@tonic-gate	*{"${callpack}::$sym"} = \&{"$def\:\:$sym"};
3090Sstevel@tonic-gate    }
3100Sstevel@tonic-gate}
3110Sstevel@tonic-gate
3120Sstevel@tonic-gatesub compile {
3130Sstevel@tonic-gate    my $pack = shift;
3140Sstevel@tonic-gate    $pack->_setup_symbols('-compile',@_);
3150Sstevel@tonic-gate}
3160Sstevel@tonic-gate
3170Sstevel@tonic-gatesub expand_tags {
3180Sstevel@tonic-gate    my($tag) = @_;
3190Sstevel@tonic-gate    return ("start_$1","end_$1") if $tag=~/^(?:\*|start_|end_)(.+)/;
3200Sstevel@tonic-gate    my(@r);
3210Sstevel@tonic-gate    return ($tag) unless $EXPORT_TAGS{$tag};
3220Sstevel@tonic-gate    foreach (@{$EXPORT_TAGS{$tag}}) {
3230Sstevel@tonic-gate	push(@r,&expand_tags($_));
3240Sstevel@tonic-gate    }
3250Sstevel@tonic-gate    return @r;
3260Sstevel@tonic-gate}
3270Sstevel@tonic-gate
3280Sstevel@tonic-gate#### Method: new
3290Sstevel@tonic-gate# The new routine.  This will check the current environment
3300Sstevel@tonic-gate# for an existing query string, and initialize itself, if so.
3310Sstevel@tonic-gate####
3320Sstevel@tonic-gatesub new {
3330Sstevel@tonic-gate  my($class,@initializer) = @_;
3340Sstevel@tonic-gate  my $self = {};
3350Sstevel@tonic-gate
3360Sstevel@tonic-gate  bless $self,ref $class || $class || $DefaultClass;
337*6287Sps156622
338*6287Sps156622  # always use a tempfile
339*6287Sps156622  $self->{'use_tempfile'} = 1;
340*6287Sps156622
3410Sstevel@tonic-gate  if (ref($initializer[0])
3420Sstevel@tonic-gate      && (UNIVERSAL::isa($initializer[0],'Apache')
3430Sstevel@tonic-gate	  ||
344667Sps156622	  UNIVERSAL::isa($initializer[0],'Apache2::RequestRec')
3450Sstevel@tonic-gate	 )) {
3460Sstevel@tonic-gate    $self->r(shift @initializer);
3470Sstevel@tonic-gate  }
3480Sstevel@tonic-gate if (ref($initializer[0])
3490Sstevel@tonic-gate     && (UNIVERSAL::isa($initializer[0],'CODE'))) {
3500Sstevel@tonic-gate    $self->upload_hook(shift @initializer, shift @initializer);
351*6287Sps156622    $self->{'use_tempfile'} = shift @initializer if (@initializer > 0);
3520Sstevel@tonic-gate  }
3530Sstevel@tonic-gate  if ($MOD_PERL) {
3540Sstevel@tonic-gate    if ($MOD_PERL == 1) {
355667Sps156622      $self->r(Apache->request) unless $self->r;
356667Sps156622      my $r = $self->r;
3570Sstevel@tonic-gate      $r->register_cleanup(\&CGI::_reset_globals);
3580Sstevel@tonic-gate    }
3590Sstevel@tonic-gate    else {
3600Sstevel@tonic-gate      # XXX: once we have the new API
3610Sstevel@tonic-gate      # will do a real PerlOptions -SetupEnv check
362667Sps156622      $self->r(Apache2::RequestUtil->request) unless $self->r;
363667Sps156622      my $r = $self->r;
3640Sstevel@tonic-gate      $r->subprocess_env unless exists $ENV{REQUEST_METHOD};
3650Sstevel@tonic-gate      $r->pool->cleanup_register(\&CGI::_reset_globals);
3660Sstevel@tonic-gate    }
3670Sstevel@tonic-gate    undef $NPH;
3680Sstevel@tonic-gate  }
3690Sstevel@tonic-gate  $self->_reset_globals if $PERLEX;
3700Sstevel@tonic-gate  $self->init(@initializer);
3710Sstevel@tonic-gate  return $self;
3720Sstevel@tonic-gate}
3730Sstevel@tonic-gate
3740Sstevel@tonic-gate# We provide a DESTROY method so that we can ensure that
3750Sstevel@tonic-gate# temporary files are closed (via Fh->DESTROY) before they
3760Sstevel@tonic-gate# are unlinked (via CGITempFile->DESTROY) because it is not
3770Sstevel@tonic-gate# possible to unlink an open file on Win32. We explicitly
3780Sstevel@tonic-gate# call DESTROY on each, rather than just undefing them and
3790Sstevel@tonic-gate# letting Perl DESTROY them by garbage collection, in case the
3800Sstevel@tonic-gate# user is still holding any reference to them as well.
3810Sstevel@tonic-gatesub DESTROY {
3820Sstevel@tonic-gate  my $self = shift;
383*6287Sps156622  if ($OS eq 'WINDOWS') {
384*6287Sps156622    foreach my $href (values %{$self->{'.tmpfiles'}}) {
385*6287Sps156622      $href->{hndl}->DESTROY if defined $href->{hndl};
386*6287Sps156622      $href->{name}->DESTROY if defined $href->{name};
387*6287Sps156622    }
3880Sstevel@tonic-gate  }
3890Sstevel@tonic-gate}
3900Sstevel@tonic-gate
3910Sstevel@tonic-gatesub r {
3920Sstevel@tonic-gate  my $self = shift;
3930Sstevel@tonic-gate  my $r = $self->{'.r'};
3940Sstevel@tonic-gate  $self->{'.r'} = shift if @_;
3950Sstevel@tonic-gate  $r;
3960Sstevel@tonic-gate}
3970Sstevel@tonic-gate
3980Sstevel@tonic-gatesub upload_hook {
399*6287Sps156622  my $self;
400*6287Sps156622  if (ref $_[0] eq 'CODE') {
401*6287Sps156622    $CGI::Q = $self = $CGI::DefaultClass->new(@_);
402*6287Sps156622  } else {
403*6287Sps156622    $self = shift;
404*6287Sps156622  }
405*6287Sps156622  my ($hook,$data,$use_tempfile) = @_;
4060Sstevel@tonic-gate  $self->{'.upload_hook'} = $hook;
4070Sstevel@tonic-gate  $self->{'.upload_data'} = $data;
408*6287Sps156622  $self->{'use_tempfile'} = $use_tempfile if defined $use_tempfile;
4090Sstevel@tonic-gate}
4100Sstevel@tonic-gate
4110Sstevel@tonic-gate#### Method: param
4120Sstevel@tonic-gate# Returns the value(s)of a named parameter.
4130Sstevel@tonic-gate# If invoked in a list context, returns the
4140Sstevel@tonic-gate# entire list.  Otherwise returns the first
4150Sstevel@tonic-gate# member of the list.
4160Sstevel@tonic-gate# If name is not provided, return a list of all
4170Sstevel@tonic-gate# the known parameters names available.
4180Sstevel@tonic-gate# If more than one argument is provided, the
4190Sstevel@tonic-gate# second and subsequent arguments are used to
4200Sstevel@tonic-gate# set the value of the parameter.
4210Sstevel@tonic-gate####
4220Sstevel@tonic-gatesub param {
4230Sstevel@tonic-gate    my($self,@p) = self_or_default(@_);
4240Sstevel@tonic-gate    return $self->all_parameters unless @p;
4250Sstevel@tonic-gate    my($name,$value,@other);
4260Sstevel@tonic-gate
4270Sstevel@tonic-gate    # For compatibility between old calling style and use_named_parameters() style,
4280Sstevel@tonic-gate    # we have to special case for a single parameter present.
4290Sstevel@tonic-gate    if (@p > 1) {
4300Sstevel@tonic-gate	($name,$value,@other) = rearrange([NAME,[DEFAULT,VALUE,VALUES]],@p);
4310Sstevel@tonic-gate	my(@values);
4320Sstevel@tonic-gate
4330Sstevel@tonic-gate	if (substr($p[0],0,1) eq '-') {
4340Sstevel@tonic-gate	    @values = defined($value) ? (ref($value) && ref($value) eq 'ARRAY' ? @{$value} : $value) : ();
4350Sstevel@tonic-gate	} else {
4360Sstevel@tonic-gate	    foreach ($value,@other) {
4370Sstevel@tonic-gate		push(@values,$_) if defined($_);
4380Sstevel@tonic-gate	    }
4390Sstevel@tonic-gate	}
4400Sstevel@tonic-gate	# If values is provided, then we set it.
441*6287Sps156622	if (@values or defined $value) {
4420Sstevel@tonic-gate	    $self->add_parameter($name);
4430Sstevel@tonic-gate	    $self->{$name}=[@values];
4440Sstevel@tonic-gate	}
4450Sstevel@tonic-gate    } else {
4460Sstevel@tonic-gate	$name = $p[0];
4470Sstevel@tonic-gate    }
4480Sstevel@tonic-gate
4490Sstevel@tonic-gate    return unless defined($name) && $self->{$name};
450*6287Sps156622
451*6287Sps156622    my @result = @{$self->{$name}};
452*6287Sps156622
453*6287Sps156622    if ($PARAM_UTF8) {
454*6287Sps156622      eval "require Encode; 1;" unless Encode->can('decode'); # bring in these functions
455*6287Sps156622      @result = map {ref $_ ? $_ : Encode::decode(utf8=>$_) } @result;
456*6287Sps156622    }
457*6287Sps156622
458*6287Sps156622    return wantarray ?  @result : $result[0];
4590Sstevel@tonic-gate}
4600Sstevel@tonic-gate
4610Sstevel@tonic-gatesub self_or_default {
4620Sstevel@tonic-gate    return @_ if defined($_[0]) && (!ref($_[0])) &&($_[0] eq 'CGI');
4630Sstevel@tonic-gate    unless (defined($_[0]) &&
4640Sstevel@tonic-gate	    (ref($_[0]) eq 'CGI' || UNIVERSAL::isa($_[0],'CGI')) # slightly optimized for common case
4650Sstevel@tonic-gate	    ) {
4660Sstevel@tonic-gate	$Q = $CGI::DefaultClass->new unless defined($Q);
4670Sstevel@tonic-gate	unshift(@_,$Q);
4680Sstevel@tonic-gate    }
4690Sstevel@tonic-gate    return wantarray ? @_ : $Q;
4700Sstevel@tonic-gate}
4710Sstevel@tonic-gate
4720Sstevel@tonic-gatesub self_or_CGI {
4730Sstevel@tonic-gate    local $^W=0;                # prevent a warning
4740Sstevel@tonic-gate    if (defined($_[0]) &&
4750Sstevel@tonic-gate	(substr(ref($_[0]),0,3) eq 'CGI'
4760Sstevel@tonic-gate	 || UNIVERSAL::isa($_[0],'CGI'))) {
4770Sstevel@tonic-gate	return @_;
4780Sstevel@tonic-gate    } else {
4790Sstevel@tonic-gate	return ($DefaultClass,@_);
4800Sstevel@tonic-gate    }
4810Sstevel@tonic-gate}
4820Sstevel@tonic-gate
4830Sstevel@tonic-gate########################################
4840Sstevel@tonic-gate# THESE METHODS ARE MORE OR LESS PRIVATE
4850Sstevel@tonic-gate# GO TO THE __DATA__ SECTION TO SEE MORE
4860Sstevel@tonic-gate# PUBLIC METHODS
4870Sstevel@tonic-gate########################################
4880Sstevel@tonic-gate
4890Sstevel@tonic-gate# Initialize the query object from the environment.
4900Sstevel@tonic-gate# If a parameter list is found, this object will be set
4910Sstevel@tonic-gate# to an associative array in which parameter names are keys
4920Sstevel@tonic-gate# and the values are stored as lists
4930Sstevel@tonic-gate# If a keyword list is found, this method creates a bogus
4940Sstevel@tonic-gate# parameter list with the single parameter 'keywords'.
4950Sstevel@tonic-gate
4960Sstevel@tonic-gatesub init {
4970Sstevel@tonic-gate  my $self = shift;
4980Sstevel@tonic-gate  my($query_string,$meth,$content_length,$fh,@lines) = ('','','','');
4990Sstevel@tonic-gate
500*6287Sps156622  my $is_xforms;
501*6287Sps156622
5020Sstevel@tonic-gate  my $initializer = shift;  # for backward compatibility
5030Sstevel@tonic-gate  local($/) = "\n";
5040Sstevel@tonic-gate
5050Sstevel@tonic-gate    # set autoescaping on by default
5060Sstevel@tonic-gate    $self->{'escape'} = 1;
5070Sstevel@tonic-gate
5080Sstevel@tonic-gate    # if we get called more than once, we want to initialize
5090Sstevel@tonic-gate    # ourselves from the original query (which may be gone
5100Sstevel@tonic-gate    # if it was read from STDIN originally.)
5110Sstevel@tonic-gate    if (defined(@QUERY_PARAM) && !defined($initializer)) {
512*6287Sps156622        for my $name (@QUERY_PARAM) {
513*6287Sps156622            my $val = $QUERY_PARAM{$name}; # always an arrayref;
514*6287Sps156622            $self->param('-name'=>$name,'-value'=> $val);
515*6287Sps156622            if (defined $val and ref $val eq 'ARRAY') {
516*6287Sps156622                for my $fh (grep {defined(fileno($_))} @$val) {
517*6287Sps156622                   seek($fh,0,0); # reset the filehandle.
518*6287Sps156622                }
519*6287Sps156622
520*6287Sps156622            }
521*6287Sps156622        }
522*6287Sps156622        $self->charset($QUERY_CHARSET);
523*6287Sps156622        $self->{'.fieldnames'} = {%QUERY_FIELDNAMES};
524*6287Sps156622        $self->{'.tmpfiles'}   = {%QUERY_TMPFILES};
525*6287Sps156622        return;
5260Sstevel@tonic-gate    }
5270Sstevel@tonic-gate
5280Sstevel@tonic-gate    $meth=$ENV{'REQUEST_METHOD'} if defined($ENV{'REQUEST_METHOD'});
5290Sstevel@tonic-gate    $content_length = defined($ENV{'CONTENT_LENGTH'}) ? $ENV{'CONTENT_LENGTH'} : 0;
5300Sstevel@tonic-gate
5310Sstevel@tonic-gate    $fh = to_filehandle($initializer) if $initializer;
5320Sstevel@tonic-gate
5330Sstevel@tonic-gate    # set charset to the safe ISO-8859-1
5340Sstevel@tonic-gate    $self->charset('ISO-8859-1');
5350Sstevel@tonic-gate
5360Sstevel@tonic-gate  METHOD: {
5370Sstevel@tonic-gate
5380Sstevel@tonic-gate      # avoid unreasonably large postings
5390Sstevel@tonic-gate      if (($POST_MAX > 0) && ($content_length > $POST_MAX)) {
540*6287Sps156622	#discard the post, unread
541*6287Sps156622	$self->cgi_error("413 Request entity too large");
542*6287Sps156622	last METHOD;
543*6287Sps156622      }
5440Sstevel@tonic-gate
5450Sstevel@tonic-gate      # Process multipart postings, but only if the initializer is
5460Sstevel@tonic-gate      # not defined.
5470Sstevel@tonic-gate      if ($meth eq 'POST'
5480Sstevel@tonic-gate	  && defined($ENV{'CONTENT_TYPE'})
5490Sstevel@tonic-gate	  && $ENV{'CONTENT_TYPE'}=~m|^multipart/form-data|
5500Sstevel@tonic-gate	  && !defined($initializer)
5510Sstevel@tonic-gate	  ) {
5520Sstevel@tonic-gate	  my($boundary) = $ENV{'CONTENT_TYPE'} =~ /boundary=\"?([^\";,]+)\"?/;
5530Sstevel@tonic-gate	  $self->read_multipart($boundary,$content_length);
5540Sstevel@tonic-gate	  last METHOD;
5550Sstevel@tonic-gate      }
5560Sstevel@tonic-gate
557*6287Sps156622      # Process XForms postings. We know that we have XForms in the
558*6287Sps156622      # following cases:
559*6287Sps156622      # method eq 'POST' && content-type eq 'application/xml'
560*6287Sps156622      # method eq 'POST' && content-type =~ /multipart\/related.+start=/
561*6287Sps156622      # There are more cases, actually, but for now, we don't support other
562*6287Sps156622      # methods for XForm posts.
563*6287Sps156622      # In a XForm POST, the QUERY_STRING is parsed normally.
564*6287Sps156622      # If the content-type is 'application/xml', we just set the param
565*6287Sps156622      # XForms:Model (referring to the xml syntax) param containing the
566*6287Sps156622      # unparsed XML data.
567*6287Sps156622      # In the case of multipart/related we set XForms:Model as above, but
568*6287Sps156622      # the other parts are available as uploads with the Content-ID as the
569*6287Sps156622      # the key.
570*6287Sps156622      # See the URL below for XForms specs on this issue.
571*6287Sps156622      # http://www.w3.org/TR/2006/REC-xforms-20060314/slice11.html#submit-options
572*6287Sps156622      if ($meth eq 'POST' && defined($ENV{'CONTENT_TYPE'})) {
573*6287Sps156622              if ($ENV{'CONTENT_TYPE'} eq 'application/xml') {
574*6287Sps156622                      my($param) = 'XForms:Model';
575*6287Sps156622                      my($value) = '';
576*6287Sps156622                      $self->add_parameter($param);
577*6287Sps156622                      $self->read_from_client(\$value,$content_length,0)
578*6287Sps156622                        if $content_length > 0;
579*6287Sps156622                      push (@{$self->{$param}},$value);
580*6287Sps156622                      $is_xforms = 1;
581*6287Sps156622              } elsif ($ENV{'CONTENT_TYPE'} =~ /multipart\/related.+boundary=\"?([^\";,]+)\"?.+start=\"?\<?([^\"\>]+)\>?\"?/) {
582*6287Sps156622                      my($boundary,$start) = ($1,$2);
583*6287Sps156622                      my($param) = 'XForms:Model';
584*6287Sps156622                      $self->add_parameter($param);
585*6287Sps156622                      my($value) = $self->read_multipart_related($start,$boundary,$content_length,0);
586*6287Sps156622                      push (@{$self->{$param}},$value);
587*6287Sps156622                      if ($MOD_PERL) {
588*6287Sps156622                              $query_string = $self->r->args;
589*6287Sps156622                      } else {
590*6287Sps156622                              $query_string = $ENV{'QUERY_STRING'} if defined $ENV{'QUERY_STRING'};
591*6287Sps156622                              $query_string ||= $ENV{'REDIRECT_QUERY_STRING'} if defined $ENV{'REDIRECT_QUERY_STRING'};
592*6287Sps156622                      }
593*6287Sps156622                      $is_xforms = 1;
594*6287Sps156622              }
595*6287Sps156622      }
596*6287Sps156622
597*6287Sps156622
5980Sstevel@tonic-gate      # If initializer is defined, then read parameters
5990Sstevel@tonic-gate      # from it.
600*6287Sps156622      if (!$is_xforms && defined($initializer)) {
6010Sstevel@tonic-gate	  if (UNIVERSAL::isa($initializer,'CGI')) {
6020Sstevel@tonic-gate	      $query_string = $initializer->query_string;
6030Sstevel@tonic-gate	      last METHOD;
6040Sstevel@tonic-gate	  }
6050Sstevel@tonic-gate	  if (ref($initializer) && ref($initializer) eq 'HASH') {
6060Sstevel@tonic-gate	      foreach (keys %$initializer) {
6070Sstevel@tonic-gate		  $self->param('-name'=>$_,'-value'=>$initializer->{$_});
6080Sstevel@tonic-gate	      }
6090Sstevel@tonic-gate	      last METHOD;
6100Sstevel@tonic-gate	  }
6110Sstevel@tonic-gate
6120Sstevel@tonic-gate          if (defined($fh) && ($fh ne '')) {
6130Sstevel@tonic-gate              while (<$fh>) {
6140Sstevel@tonic-gate                  chomp;
6150Sstevel@tonic-gate                  last if /^=/;
6160Sstevel@tonic-gate                  push(@lines,$_);
6170Sstevel@tonic-gate              }
6180Sstevel@tonic-gate              # massage back into standard format
6190Sstevel@tonic-gate              if ("@lines" =~ /=/) {
6200Sstevel@tonic-gate                  $query_string=join("&",@lines);
6210Sstevel@tonic-gate              } else {
6220Sstevel@tonic-gate                  $query_string=join("+",@lines);
6230Sstevel@tonic-gate              }
6240Sstevel@tonic-gate              last METHOD;
6250Sstevel@tonic-gate          }
6260Sstevel@tonic-gate
6270Sstevel@tonic-gate	  # last chance -- treat it as a string
6280Sstevel@tonic-gate	  $initializer = $$initializer if ref($initializer) eq 'SCALAR';
6290Sstevel@tonic-gate	  $query_string = $initializer;
6300Sstevel@tonic-gate
6310Sstevel@tonic-gate	  last METHOD;
6320Sstevel@tonic-gate      }
6330Sstevel@tonic-gate
6340Sstevel@tonic-gate      # If method is GET or HEAD, fetch the query from
6350Sstevel@tonic-gate      # the environment.
636*6287Sps156622      if ($is_xforms || $meth=~/^(GET|HEAD)$/) {
6370Sstevel@tonic-gate	  if ($MOD_PERL) {
6380Sstevel@tonic-gate	    $query_string = $self->r->args;
6390Sstevel@tonic-gate	  } else {
6400Sstevel@tonic-gate	      $query_string = $ENV{'QUERY_STRING'} if defined $ENV{'QUERY_STRING'};
6410Sstevel@tonic-gate	      $query_string ||= $ENV{'REDIRECT_QUERY_STRING'} if defined $ENV{'REDIRECT_QUERY_STRING'};
6420Sstevel@tonic-gate	  }
6430Sstevel@tonic-gate	  last METHOD;
6440Sstevel@tonic-gate      }
6450Sstevel@tonic-gate
646*6287Sps156622      if ($meth eq 'POST' || $meth eq 'PUT') {
6470Sstevel@tonic-gate	  $self->read_from_client(\$query_string,$content_length,0)
6480Sstevel@tonic-gate	      if $content_length > 0;
6490Sstevel@tonic-gate	  # Some people want to have their cake and eat it too!
6500Sstevel@tonic-gate	  # Uncomment this line to have the contents of the query string
6510Sstevel@tonic-gate	  # APPENDED to the POST data.
6520Sstevel@tonic-gate	  # $query_string .= (length($query_string) ? '&' : '') . $ENV{'QUERY_STRING'} if defined $ENV{'QUERY_STRING'};
6530Sstevel@tonic-gate	  last METHOD;
6540Sstevel@tonic-gate      }
6550Sstevel@tonic-gate
6560Sstevel@tonic-gate      # If $meth is not of GET, POST or HEAD, assume we're being debugged offline.
6570Sstevel@tonic-gate      # Check the command line and then the standard input for data.
6580Sstevel@tonic-gate      # We use the shellwords package in order to behave the way that
6590Sstevel@tonic-gate      # UN*X programmers expect.
6600Sstevel@tonic-gate      if ($DEBUG)
6610Sstevel@tonic-gate      {
6620Sstevel@tonic-gate          my $cmdline_ret = read_from_cmdline();
6630Sstevel@tonic-gate          $query_string = $cmdline_ret->{'query_string'};
6640Sstevel@tonic-gate          if (defined($cmdline_ret->{'subpath'}))
6650Sstevel@tonic-gate          {
6660Sstevel@tonic-gate              $self->path_info($cmdline_ret->{'subpath'});
6670Sstevel@tonic-gate          }
6680Sstevel@tonic-gate      }
6690Sstevel@tonic-gate  }
6700Sstevel@tonic-gate
6710Sstevel@tonic-gate# YL: Begin Change for XML handler 10/19/2001
672*6287Sps156622    if (!$is_xforms && ($meth eq 'POST' || $meth eq 'PUT')
6730Sstevel@tonic-gate        && defined($ENV{'CONTENT_TYPE'})
6740Sstevel@tonic-gate        && $ENV{'CONTENT_TYPE'} !~ m|^application/x-www-form-urlencoded|
6750Sstevel@tonic-gate	&& $ENV{'CONTENT_TYPE'} !~ m|^multipart/form-data| ) {
676*6287Sps156622        my($param) = $meth . 'DATA' ;
6770Sstevel@tonic-gate        $self->add_parameter($param) ;
6780Sstevel@tonic-gate      push (@{$self->{$param}},$query_string);
6790Sstevel@tonic-gate      undef $query_string ;
6800Sstevel@tonic-gate    }
6810Sstevel@tonic-gate# YL: End Change for XML handler 10/19/2001
6820Sstevel@tonic-gate
6830Sstevel@tonic-gate    # We now have the query string in hand.  We do slightly
6840Sstevel@tonic-gate    # different things for keyword lists and parameter lists.
6850Sstevel@tonic-gate    if (defined $query_string && length $query_string) {
6860Sstevel@tonic-gate	if ($query_string =~ /[&=;]/) {
6870Sstevel@tonic-gate	    $self->parse_params($query_string);
6880Sstevel@tonic-gate	} else {
6890Sstevel@tonic-gate	    $self->add_parameter('keywords');
6900Sstevel@tonic-gate	    $self->{'keywords'} = [$self->parse_keywordlist($query_string)];
6910Sstevel@tonic-gate	}
6920Sstevel@tonic-gate    }
6930Sstevel@tonic-gate
6940Sstevel@tonic-gate    # Special case.  Erase everything if there is a field named
6950Sstevel@tonic-gate    # .defaults.
6960Sstevel@tonic-gate    if ($self->param('.defaults')) {
6970Sstevel@tonic-gate      $self->delete_all();
6980Sstevel@tonic-gate    }
6990Sstevel@tonic-gate
7000Sstevel@tonic-gate    # Associative array containing our defined fieldnames
7010Sstevel@tonic-gate    $self->{'.fieldnames'} = {};
7020Sstevel@tonic-gate    foreach ($self->param('.cgifields')) {
7030Sstevel@tonic-gate	$self->{'.fieldnames'}->{$_}++;
7040Sstevel@tonic-gate    }
7050Sstevel@tonic-gate
7060Sstevel@tonic-gate    # Clear out our default submission button flag if present
7070Sstevel@tonic-gate    $self->delete('.submit');
7080Sstevel@tonic-gate    $self->delete('.cgifields');
7090Sstevel@tonic-gate
7100Sstevel@tonic-gate    $self->save_request unless defined $initializer;
7110Sstevel@tonic-gate}
7120Sstevel@tonic-gate
7130Sstevel@tonic-gate# FUNCTIONS TO OVERRIDE:
7140Sstevel@tonic-gate# Turn a string into a filehandle
7150Sstevel@tonic-gatesub to_filehandle {
7160Sstevel@tonic-gate    my $thingy = shift;
7170Sstevel@tonic-gate    return undef unless $thingy;
7180Sstevel@tonic-gate    return $thingy if UNIVERSAL::isa($thingy,'GLOB');
7190Sstevel@tonic-gate    return $thingy if UNIVERSAL::isa($thingy,'FileHandle');
7200Sstevel@tonic-gate    if (!ref($thingy)) {
7210Sstevel@tonic-gate	my $caller = 1;
7220Sstevel@tonic-gate	while (my $package = caller($caller++)) {
7230Sstevel@tonic-gate	    my($tmp) = $thingy=~/[\':]/ ? $thingy : "$package\:\:$thingy";
7240Sstevel@tonic-gate	    return $tmp if defined(fileno($tmp));
7250Sstevel@tonic-gate	}
7260Sstevel@tonic-gate    }
7270Sstevel@tonic-gate    return undef;
7280Sstevel@tonic-gate}
7290Sstevel@tonic-gate
7300Sstevel@tonic-gate# send output to the browser
7310Sstevel@tonic-gatesub put {
7320Sstevel@tonic-gate    my($self,@p) = self_or_default(@_);
7330Sstevel@tonic-gate    $self->print(@p);
7340Sstevel@tonic-gate}
7350Sstevel@tonic-gate
7360Sstevel@tonic-gate# print to standard output (for overriding in mod_perl)
7370Sstevel@tonic-gatesub print {
7380Sstevel@tonic-gate    shift;
7390Sstevel@tonic-gate    CORE::print(@_);
7400Sstevel@tonic-gate}
7410Sstevel@tonic-gate
7420Sstevel@tonic-gate# get/set last cgi_error
7430Sstevel@tonic-gatesub cgi_error {
7440Sstevel@tonic-gate    my ($self,$err) = self_or_default(@_);
7450Sstevel@tonic-gate    $self->{'.cgi_error'} = $err if defined $err;
7460Sstevel@tonic-gate    return $self->{'.cgi_error'};
7470Sstevel@tonic-gate}
7480Sstevel@tonic-gate
7490Sstevel@tonic-gatesub save_request {
7500Sstevel@tonic-gate    my($self) = @_;
7510Sstevel@tonic-gate    # We're going to play with the package globals now so that if we get called
7520Sstevel@tonic-gate    # again, we initialize ourselves in exactly the same way.  This allows
7530Sstevel@tonic-gate    # us to have several of these objects.
7540Sstevel@tonic-gate    @QUERY_PARAM = $self->param; # save list of parameters
7550Sstevel@tonic-gate    foreach (@QUERY_PARAM) {
7560Sstevel@tonic-gate      next unless defined $_;
7570Sstevel@tonic-gate      $QUERY_PARAM{$_}=$self->{$_};
7580Sstevel@tonic-gate    }
7590Sstevel@tonic-gate    $QUERY_CHARSET = $self->charset;
7600Sstevel@tonic-gate    %QUERY_FIELDNAMES = %{$self->{'.fieldnames'}};
761*6287Sps156622    %QUERY_TMPFILES   = %{ $self->{'.tmpfiles'} || {} };
7620Sstevel@tonic-gate}
7630Sstevel@tonic-gate
7640Sstevel@tonic-gatesub parse_params {
7650Sstevel@tonic-gate    my($self,$tosplit) = @_;
7660Sstevel@tonic-gate    my(@pairs) = split(/[&;]/,$tosplit);
7670Sstevel@tonic-gate    my($param,$value);
7680Sstevel@tonic-gate    foreach (@pairs) {
7690Sstevel@tonic-gate	($param,$value) = split('=',$_,2);
7700Sstevel@tonic-gate	next unless defined $param;
7710Sstevel@tonic-gate	next if $NO_UNDEF_PARAMS and not defined $value;
7720Sstevel@tonic-gate	$value = '' unless defined $value;
7730Sstevel@tonic-gate	$param = unescape($param);
7740Sstevel@tonic-gate	$value = unescape($value);
7750Sstevel@tonic-gate	$self->add_parameter($param);
7760Sstevel@tonic-gate	push (@{$self->{$param}},$value);
7770Sstevel@tonic-gate    }
7780Sstevel@tonic-gate}
7790Sstevel@tonic-gate
7800Sstevel@tonic-gatesub add_parameter {
7810Sstevel@tonic-gate    my($self,$param)=@_;
7820Sstevel@tonic-gate    return unless defined $param;
7830Sstevel@tonic-gate    push (@{$self->{'.parameters'}},$param)
7840Sstevel@tonic-gate	unless defined($self->{$param});
7850Sstevel@tonic-gate}
7860Sstevel@tonic-gate
7870Sstevel@tonic-gatesub all_parameters {
7880Sstevel@tonic-gate    my $self = shift;
7890Sstevel@tonic-gate    return () unless defined($self) && $self->{'.parameters'};
7900Sstevel@tonic-gate    return () unless @{$self->{'.parameters'}};
7910Sstevel@tonic-gate    return @{$self->{'.parameters'}};
7920Sstevel@tonic-gate}
7930Sstevel@tonic-gate
7940Sstevel@tonic-gate# put a filehandle into binary mode (DOS)
7950Sstevel@tonic-gatesub binmode {
7960Sstevel@tonic-gate    return unless defined($_[1]) && defined fileno($_[1]);
7970Sstevel@tonic-gate    CORE::binmode($_[1]);
7980Sstevel@tonic-gate}
7990Sstevel@tonic-gate
8000Sstevel@tonic-gatesub _make_tag_func {
8010Sstevel@tonic-gate    my ($self,$tagname) = @_;
8020Sstevel@tonic-gate    my $func = qq(
8030Sstevel@tonic-gate	sub $tagname {
8040Sstevel@tonic-gate         my (\$q,\$a,\@rest) = self_or_default(\@_);
8050Sstevel@tonic-gate         my(\$attr) = '';
8060Sstevel@tonic-gate	 if (ref(\$a) && ref(\$a) eq 'HASH') {
8070Sstevel@tonic-gate	    my(\@attr) = make_attributes(\$a,\$q->{'escape'});
8080Sstevel@tonic-gate	    \$attr = " \@attr" if \@attr;
8090Sstevel@tonic-gate	  } else {
8100Sstevel@tonic-gate	    unshift \@rest,\$a if defined \$a;
8110Sstevel@tonic-gate	  }
8120Sstevel@tonic-gate	);
8130Sstevel@tonic-gate    if ($tagname=~/start_(\w+)/i) {
8140Sstevel@tonic-gate	$func .= qq! return "<\L$1\E\$attr>";} !;
8150Sstevel@tonic-gate    } elsif ($tagname=~/end_(\w+)/i) {
8160Sstevel@tonic-gate	$func .= qq! return "<\L/$1\E>"; } !;
8170Sstevel@tonic-gate    } else {
8180Sstevel@tonic-gate	$func .= qq#
8190Sstevel@tonic-gate	    return \$XHTML ? "\L<$tagname\E\$attr />" : "\L<$tagname\E\$attr>" unless \@rest;
8200Sstevel@tonic-gate	    my(\$tag,\$untag) = ("\L<$tagname\E\$attr>","\L</$tagname>\E");
8210Sstevel@tonic-gate	    my \@result = map { "\$tag\$_\$untag" }
8220Sstevel@tonic-gate                              (ref(\$rest[0]) eq 'ARRAY') ? \@{\$rest[0]} : "\@rest";
8230Sstevel@tonic-gate	    return "\@result";
8240Sstevel@tonic-gate            }#;
8250Sstevel@tonic-gate    }
8260Sstevel@tonic-gatereturn $func;
8270Sstevel@tonic-gate}
8280Sstevel@tonic-gate
8290Sstevel@tonic-gatesub AUTOLOAD {
8300Sstevel@tonic-gate    print STDERR "CGI::AUTOLOAD for $AUTOLOAD\n" if $CGI::AUTOLOAD_DEBUG;
8310Sstevel@tonic-gate    my $func = &_compile;
8320Sstevel@tonic-gate    goto &$func;
8330Sstevel@tonic-gate}
8340Sstevel@tonic-gate
8350Sstevel@tonic-gatesub _compile {
8360Sstevel@tonic-gate    my($func) = $AUTOLOAD;
8370Sstevel@tonic-gate    my($pack,$func_name);
8380Sstevel@tonic-gate    {
8390Sstevel@tonic-gate	local($1,$2); # this fixes an obscure variable suicide problem.
8400Sstevel@tonic-gate	$func=~/(.+)::([^:]+)$/;
8410Sstevel@tonic-gate	($pack,$func_name) = ($1,$2);
8420Sstevel@tonic-gate	$pack=~s/::SUPER$//;	# fix another obscure problem
8430Sstevel@tonic-gate	$pack = ${"$pack\:\:AutoloadClass"} || $CGI::DefaultClass
8440Sstevel@tonic-gate	    unless defined(${"$pack\:\:AUTOLOADED_ROUTINES"});
8450Sstevel@tonic-gate
8460Sstevel@tonic-gate        my($sub) = \%{"$pack\:\:SUBS"};
8470Sstevel@tonic-gate        unless (%$sub) {
8480Sstevel@tonic-gate	   my($auto) = \${"$pack\:\:AUTOLOADED_ROUTINES"};
849667Sps156622	   local ($@,$!);
8500Sstevel@tonic-gate	   eval "package $pack; $$auto";
8510Sstevel@tonic-gate	   croak("$AUTOLOAD: $@") if $@;
8520Sstevel@tonic-gate           $$auto = '';  # Free the unneeded storage (but don't undef it!!!)
8530Sstevel@tonic-gate       }
8540Sstevel@tonic-gate       my($code) = $sub->{$func_name};
8550Sstevel@tonic-gate
8560Sstevel@tonic-gate       $code = "sub $AUTOLOAD { }" if (!$code and $func_name eq 'DESTROY');
8570Sstevel@tonic-gate       if (!$code) {
8580Sstevel@tonic-gate	   (my $base = $func_name) =~ s/^(start_|end_)//i;
8590Sstevel@tonic-gate	   if ($EXPORT{':any'} ||
8600Sstevel@tonic-gate	       $EXPORT{'-any'} ||
8610Sstevel@tonic-gate	       $EXPORT{$base} ||
8620Sstevel@tonic-gate	       (%EXPORT_OK || grep(++$EXPORT_OK{$_},&expand_tags(':html')))
8630Sstevel@tonic-gate	           && $EXPORT_OK{$base}) {
8640Sstevel@tonic-gate	       $code = $CGI::DefaultClass->_make_tag_func($func_name);
8650Sstevel@tonic-gate	   }
8660Sstevel@tonic-gate       }
8670Sstevel@tonic-gate       croak("Undefined subroutine $AUTOLOAD\n") unless $code;
868667Sps156622       local ($@,$!);
8690Sstevel@tonic-gate       eval "package $pack; $code";
8700Sstevel@tonic-gate       if ($@) {
8710Sstevel@tonic-gate	   $@ =~ s/ at .*\n//;
8720Sstevel@tonic-gate	   croak("$AUTOLOAD: $@");
8730Sstevel@tonic-gate       }
8740Sstevel@tonic-gate    }
8750Sstevel@tonic-gate    CORE::delete($sub->{$func_name});  #free storage
8760Sstevel@tonic-gate    return "$pack\:\:$func_name";
8770Sstevel@tonic-gate}
8780Sstevel@tonic-gate
8790Sstevel@tonic-gatesub _selected {
8800Sstevel@tonic-gate  my $self = shift;
8810Sstevel@tonic-gate  my $value = shift;
8820Sstevel@tonic-gate  return '' unless $value;
883*6287Sps156622  return $XHTML ? qq(selected="selected" ) : qq(selected );
8840Sstevel@tonic-gate}
8850Sstevel@tonic-gate
8860Sstevel@tonic-gatesub _checked {
8870Sstevel@tonic-gate  my $self = shift;
8880Sstevel@tonic-gate  my $value = shift;
8890Sstevel@tonic-gate  return '' unless $value;
890*6287Sps156622  return $XHTML ? qq(checked="checked" ) : qq(checked );
8910Sstevel@tonic-gate}
8920Sstevel@tonic-gate
8930Sstevel@tonic-gatesub _reset_globals { initialize_globals(); }
8940Sstevel@tonic-gate
8950Sstevel@tonic-gatesub _setup_symbols {
8960Sstevel@tonic-gate    my $self = shift;
8970Sstevel@tonic-gate    my $compile = 0;
8980Sstevel@tonic-gate
8990Sstevel@tonic-gate    # to avoid reexporting unwanted variables
9000Sstevel@tonic-gate    undef %EXPORT;
9010Sstevel@tonic-gate
9020Sstevel@tonic-gate    foreach (@_) {
9030Sstevel@tonic-gate	$HEADERS_ONCE++,         next if /^[:-]unique_headers$/;
9040Sstevel@tonic-gate	$NPH++,                  next if /^[:-]nph$/;
9050Sstevel@tonic-gate	$NOSTICKY++,             next if /^[:-]nosticky$/;
9060Sstevel@tonic-gate	$DEBUG=0,                next if /^[:-]no_?[Dd]ebug$/;
9070Sstevel@tonic-gate	$DEBUG=2,                next if /^[:-][Dd]ebug$/;
9080Sstevel@tonic-gate	$USE_PARAM_SEMICOLONS++, next if /^[:-]newstyle_urls$/;
909*6287Sps156622	$PARAM_UTF8++,           next if /^[:-]utf8$/;
9100Sstevel@tonic-gate	$XHTML++,                next if /^[:-]xhtml$/;
9110Sstevel@tonic-gate	$XHTML=0,                next if /^[:-]no_?xhtml$/;
9120Sstevel@tonic-gate	$USE_PARAM_SEMICOLONS=0, next if /^[:-]oldstyle_urls$/;
9130Sstevel@tonic-gate	$PRIVATE_TEMPFILES++,    next if /^[:-]private_tempfiles$/;
914*6287Sps156622	$TABINDEX++,             next if /^[:-]tabindex$/;
915667Sps156622	$CLOSE_UPLOAD_FILES++,   next if /^[:-]close_upload_files$/;
9160Sstevel@tonic-gate	$EXPORT{$_}++,           next if /^[:-]any$/;
9170Sstevel@tonic-gate	$compile++,              next if /^[:-]compile$/;
9180Sstevel@tonic-gate	$NO_UNDEF_PARAMS++,      next if /^[:-]no_undef_params$/;
9190Sstevel@tonic-gate
9200Sstevel@tonic-gate	# This is probably extremely evil code -- to be deleted some day.
9210Sstevel@tonic-gate	if (/^[-]autoload$/) {
9220Sstevel@tonic-gate	    my($pkg) = caller(1);
9230Sstevel@tonic-gate	    *{"${pkg}::AUTOLOAD"} = sub {
9240Sstevel@tonic-gate		my($routine) = $AUTOLOAD;
9250Sstevel@tonic-gate		$routine =~ s/^.*::/CGI::/;
9260Sstevel@tonic-gate		&$routine;
9270Sstevel@tonic-gate	    };
9280Sstevel@tonic-gate	    next;
9290Sstevel@tonic-gate	}
9300Sstevel@tonic-gate
9310Sstevel@tonic-gate	foreach (&expand_tags($_)) {
9320Sstevel@tonic-gate	    tr/a-zA-Z0-9_//cd;  # don't allow weird function names
9330Sstevel@tonic-gate	    $EXPORT{$_}++;
9340Sstevel@tonic-gate	}
9350Sstevel@tonic-gate    }
9360Sstevel@tonic-gate    _compile_all(keys %EXPORT) if $compile;
9370Sstevel@tonic-gate    @SAVED_SYMBOLS = @_;
9380Sstevel@tonic-gate}
9390Sstevel@tonic-gate
9400Sstevel@tonic-gatesub charset {
9410Sstevel@tonic-gate  my ($self,$charset) = self_or_default(@_);
9420Sstevel@tonic-gate  $self->{'.charset'} = $charset if defined $charset;
9430Sstevel@tonic-gate  $self->{'.charset'};
9440Sstevel@tonic-gate}
9450Sstevel@tonic-gate
946667Sps156622sub element_id {
947667Sps156622  my ($self,$new_value) = self_or_default(@_);
948667Sps156622  $self->{'.elid'} = $new_value if defined $new_value;
949667Sps156622  sprintf('%010d',$self->{'.elid'}++);
950667Sps156622}
951667Sps156622
952667Sps156622sub element_tab {
953667Sps156622  my ($self,$new_value) = self_or_default(@_);
954667Sps156622  $self->{'.etab'} ||= 1;
955667Sps156622  $self->{'.etab'} = $new_value if defined $new_value;
956*6287Sps156622  my $tab = $self->{'.etab'}++;
957*6287Sps156622  return '' unless $TABINDEX or defined $new_value;
958*6287Sps156622  return qq(tabindex="$tab" );
959667Sps156622}
960667Sps156622
9610Sstevel@tonic-gate###############################################################################
9620Sstevel@tonic-gate################# THESE FUNCTIONS ARE AUTOLOADED ON DEMAND ####################
9630Sstevel@tonic-gate###############################################################################
9640Sstevel@tonic-gate$AUTOLOADED_ROUTINES = '';      # get rid of -w warning
9650Sstevel@tonic-gate$AUTOLOADED_ROUTINES=<<'END_OF_AUTOLOAD';
9660Sstevel@tonic-gate
9670Sstevel@tonic-gate%SUBS = (
9680Sstevel@tonic-gate
9690Sstevel@tonic-gate'URL_ENCODED'=> <<'END_OF_FUNC',
9700Sstevel@tonic-gatesub URL_ENCODED { 'application/x-www-form-urlencoded'; }
9710Sstevel@tonic-gateEND_OF_FUNC
9720Sstevel@tonic-gate
9730Sstevel@tonic-gate'MULTIPART' => <<'END_OF_FUNC',
9740Sstevel@tonic-gatesub MULTIPART {  'multipart/form-data'; }
9750Sstevel@tonic-gateEND_OF_FUNC
9760Sstevel@tonic-gate
9770Sstevel@tonic-gate'SERVER_PUSH' => <<'END_OF_FUNC',
9780Sstevel@tonic-gatesub SERVER_PUSH { 'multipart/x-mixed-replace;boundary="' . shift() . '"'; }
9790Sstevel@tonic-gateEND_OF_FUNC
9800Sstevel@tonic-gate
9810Sstevel@tonic-gate'new_MultipartBuffer' => <<'END_OF_FUNC',
9820Sstevel@tonic-gate# Create a new multipart buffer
9830Sstevel@tonic-gatesub new_MultipartBuffer {
9840Sstevel@tonic-gate    my($self,$boundary,$length) = @_;
9850Sstevel@tonic-gate    return MultipartBuffer->new($self,$boundary,$length);
9860Sstevel@tonic-gate}
9870Sstevel@tonic-gateEND_OF_FUNC
9880Sstevel@tonic-gate
9890Sstevel@tonic-gate'read_from_client' => <<'END_OF_FUNC',
9900Sstevel@tonic-gate# Read data from a file handle
9910Sstevel@tonic-gatesub read_from_client {
9920Sstevel@tonic-gate    my($self, $buff, $len, $offset) = @_;
9930Sstevel@tonic-gate    local $^W=0;                # prevent a warning
9940Sstevel@tonic-gate    return $MOD_PERL
9950Sstevel@tonic-gate        ? $self->r->read($$buff, $len, $offset)
9960Sstevel@tonic-gate        : read(\*STDIN, $$buff, $len, $offset);
9970Sstevel@tonic-gate}
9980Sstevel@tonic-gateEND_OF_FUNC
9990Sstevel@tonic-gate
10000Sstevel@tonic-gate'delete' => <<'END_OF_FUNC',
10010Sstevel@tonic-gate#### Method: delete
10020Sstevel@tonic-gate# Deletes the named parameter entirely.
10030Sstevel@tonic-gate####
10040Sstevel@tonic-gatesub delete {
10050Sstevel@tonic-gate    my($self,@p) = self_or_default(@_);
10060Sstevel@tonic-gate    my(@names) = rearrange([NAME],@p);
10070Sstevel@tonic-gate    my @to_delete = ref($names[0]) eq 'ARRAY' ? @$names[0] : @names;
10080Sstevel@tonic-gate    my %to_delete;
10090Sstevel@tonic-gate    foreach my $name (@to_delete)
10100Sstevel@tonic-gate    {
10110Sstevel@tonic-gate        CORE::delete $self->{$name};
10120Sstevel@tonic-gate        CORE::delete $self->{'.fieldnames'}->{$name};
10130Sstevel@tonic-gate        $to_delete{$name}++;
10140Sstevel@tonic-gate    }
10150Sstevel@tonic-gate    @{$self->{'.parameters'}}=grep { !exists($to_delete{$_}) } $self->param();
1016667Sps156622    return;
10170Sstevel@tonic-gate}
10180Sstevel@tonic-gateEND_OF_FUNC
10190Sstevel@tonic-gate
10200Sstevel@tonic-gate#### Method: import_names
10210Sstevel@tonic-gate# Import all parameters into the given namespace.
10220Sstevel@tonic-gate# Assumes namespace 'Q' if not specified
10230Sstevel@tonic-gate####
10240Sstevel@tonic-gate'import_names' => <<'END_OF_FUNC',
10250Sstevel@tonic-gatesub import_names {
10260Sstevel@tonic-gate    my($self,$namespace,$delete) = self_or_default(@_);
10270Sstevel@tonic-gate    $namespace = 'Q' unless defined($namespace);
10280Sstevel@tonic-gate    die "Can't import names into \"main\"\n" if \%{"${namespace}::"} == \%::;
10290Sstevel@tonic-gate    if ($delete || $MOD_PERL || exists $ENV{'FCGI_ROLE'}) {
10300Sstevel@tonic-gate	# can anyone find an easier way to do this?
10310Sstevel@tonic-gate	foreach (keys %{"${namespace}::"}) {
10320Sstevel@tonic-gate	    local *symbol = "${namespace}::${_}";
10330Sstevel@tonic-gate	    undef $symbol;
10340Sstevel@tonic-gate	    undef @symbol;
10350Sstevel@tonic-gate	    undef %symbol;
10360Sstevel@tonic-gate	}
10370Sstevel@tonic-gate    }
10380Sstevel@tonic-gate    my($param,@value,$var);
10390Sstevel@tonic-gate    foreach $param ($self->param) {
10400Sstevel@tonic-gate	# protect against silly names
10410Sstevel@tonic-gate	($var = $param)=~tr/a-zA-Z0-9_/_/c;
10420Sstevel@tonic-gate	$var =~ s/^(?=\d)/_/;
10430Sstevel@tonic-gate	local *symbol = "${namespace}::$var";
10440Sstevel@tonic-gate	@value = $self->param($param);
10450Sstevel@tonic-gate	@symbol = @value;
10460Sstevel@tonic-gate	$symbol = $value[0];
10470Sstevel@tonic-gate    }
10480Sstevel@tonic-gate}
10490Sstevel@tonic-gateEND_OF_FUNC
10500Sstevel@tonic-gate
10510Sstevel@tonic-gate#### Method: keywords
10520Sstevel@tonic-gate# Keywords acts a bit differently.  Calling it in a list context
10530Sstevel@tonic-gate# returns the list of keywords.
10540Sstevel@tonic-gate# Calling it in a scalar context gives you the size of the list.
10550Sstevel@tonic-gate####
10560Sstevel@tonic-gate'keywords' => <<'END_OF_FUNC',
10570Sstevel@tonic-gatesub keywords {
10580Sstevel@tonic-gate    my($self,@values) = self_or_default(@_);
10590Sstevel@tonic-gate    # If values is provided, then we set it.
10600Sstevel@tonic-gate    $self->{'keywords'}=[@values] if @values;
10610Sstevel@tonic-gate    my(@result) = defined($self->{'keywords'}) ? @{$self->{'keywords'}} : ();
10620Sstevel@tonic-gate    @result;
10630Sstevel@tonic-gate}
10640Sstevel@tonic-gateEND_OF_FUNC
10650Sstevel@tonic-gate
10660Sstevel@tonic-gate# These are some tie() interfaces for compatibility
10670Sstevel@tonic-gate# with Steve Brenner's cgi-lib.pl routines
10680Sstevel@tonic-gate'Vars' => <<'END_OF_FUNC',
10690Sstevel@tonic-gatesub Vars {
10700Sstevel@tonic-gate    my $q = shift;
10710Sstevel@tonic-gate    my %in;
10720Sstevel@tonic-gate    tie(%in,CGI,$q);
10730Sstevel@tonic-gate    return %in if wantarray;
10740Sstevel@tonic-gate    return \%in;
10750Sstevel@tonic-gate}
10760Sstevel@tonic-gateEND_OF_FUNC
10770Sstevel@tonic-gate
10780Sstevel@tonic-gate# These are some tie() interfaces for compatibility
10790Sstevel@tonic-gate# with Steve Brenner's cgi-lib.pl routines
10800Sstevel@tonic-gate'ReadParse' => <<'END_OF_FUNC',
10810Sstevel@tonic-gatesub ReadParse {
10820Sstevel@tonic-gate    local(*in);
10830Sstevel@tonic-gate    if (@_) {
10840Sstevel@tonic-gate	*in = $_[0];
10850Sstevel@tonic-gate    } else {
10860Sstevel@tonic-gate	my $pkg = caller();
10870Sstevel@tonic-gate	*in=*{"${pkg}::in"};
10880Sstevel@tonic-gate    }
10890Sstevel@tonic-gate    tie(%in,CGI);
10900Sstevel@tonic-gate    return scalar(keys %in);
10910Sstevel@tonic-gate}
10920Sstevel@tonic-gateEND_OF_FUNC
10930Sstevel@tonic-gate
10940Sstevel@tonic-gate'PrintHeader' => <<'END_OF_FUNC',
10950Sstevel@tonic-gatesub PrintHeader {
10960Sstevel@tonic-gate    my($self) = self_or_default(@_);
10970Sstevel@tonic-gate    return $self->header();
10980Sstevel@tonic-gate}
10990Sstevel@tonic-gateEND_OF_FUNC
11000Sstevel@tonic-gate
11010Sstevel@tonic-gate'HtmlTop' => <<'END_OF_FUNC',
11020Sstevel@tonic-gatesub HtmlTop {
11030Sstevel@tonic-gate    my($self,@p) = self_or_default(@_);
11040Sstevel@tonic-gate    return $self->start_html(@p);
11050Sstevel@tonic-gate}
11060Sstevel@tonic-gateEND_OF_FUNC
11070Sstevel@tonic-gate
11080Sstevel@tonic-gate'HtmlBot' => <<'END_OF_FUNC',
11090Sstevel@tonic-gatesub HtmlBot {
11100Sstevel@tonic-gate    my($self,@p) = self_or_default(@_);
11110Sstevel@tonic-gate    return $self->end_html(@p);
11120Sstevel@tonic-gate}
11130Sstevel@tonic-gateEND_OF_FUNC
11140Sstevel@tonic-gate
11150Sstevel@tonic-gate'SplitParam' => <<'END_OF_FUNC',
11160Sstevel@tonic-gatesub SplitParam {
11170Sstevel@tonic-gate    my ($param) = @_;
11180Sstevel@tonic-gate    my (@params) = split ("\0", $param);
11190Sstevel@tonic-gate    return (wantarray ? @params : $params[0]);
11200Sstevel@tonic-gate}
11210Sstevel@tonic-gateEND_OF_FUNC
11220Sstevel@tonic-gate
11230Sstevel@tonic-gate'MethGet' => <<'END_OF_FUNC',
11240Sstevel@tonic-gatesub MethGet {
11250Sstevel@tonic-gate    return request_method() eq 'GET';
11260Sstevel@tonic-gate}
11270Sstevel@tonic-gateEND_OF_FUNC
11280Sstevel@tonic-gate
11290Sstevel@tonic-gate'MethPost' => <<'END_OF_FUNC',
11300Sstevel@tonic-gatesub MethPost {
11310Sstevel@tonic-gate    return request_method() eq 'POST';
11320Sstevel@tonic-gate}
11330Sstevel@tonic-gateEND_OF_FUNC
11340Sstevel@tonic-gate
11350Sstevel@tonic-gate'TIEHASH' => <<'END_OF_FUNC',
11360Sstevel@tonic-gatesub TIEHASH {
11370Sstevel@tonic-gate    my $class = shift;
11380Sstevel@tonic-gate    my $arg   = $_[0];
11390Sstevel@tonic-gate    if (ref($arg) && UNIVERSAL::isa($arg,'CGI')) {
11400Sstevel@tonic-gate       return $arg;
11410Sstevel@tonic-gate    }
11420Sstevel@tonic-gate    return $Q ||= $class->new(@_);
11430Sstevel@tonic-gate}
11440Sstevel@tonic-gateEND_OF_FUNC
11450Sstevel@tonic-gate
11460Sstevel@tonic-gate'STORE' => <<'END_OF_FUNC',
11470Sstevel@tonic-gatesub STORE {
11480Sstevel@tonic-gate    my $self = shift;
11490Sstevel@tonic-gate    my $tag  = shift;
11500Sstevel@tonic-gate    my $vals = shift;
11510Sstevel@tonic-gate    my @vals = index($vals,"\0")!=-1 ? split("\0",$vals) : $vals;
11520Sstevel@tonic-gate    $self->param(-name=>$tag,-value=>\@vals);
11530Sstevel@tonic-gate}
11540Sstevel@tonic-gateEND_OF_FUNC
11550Sstevel@tonic-gate
11560Sstevel@tonic-gate'FETCH' => <<'END_OF_FUNC',
11570Sstevel@tonic-gatesub FETCH {
11580Sstevel@tonic-gate    return $_[0] if $_[1] eq 'CGI';
11590Sstevel@tonic-gate    return undef unless defined $_[0]->param($_[1]);
11600Sstevel@tonic-gate    return join("\0",$_[0]->param($_[1]));
11610Sstevel@tonic-gate}
11620Sstevel@tonic-gateEND_OF_FUNC
11630Sstevel@tonic-gate
11640Sstevel@tonic-gate'FIRSTKEY' => <<'END_OF_FUNC',
11650Sstevel@tonic-gatesub FIRSTKEY {
11660Sstevel@tonic-gate    $_[0]->{'.iterator'}=0;
11670Sstevel@tonic-gate    $_[0]->{'.parameters'}->[$_[0]->{'.iterator'}++];
11680Sstevel@tonic-gate}
11690Sstevel@tonic-gateEND_OF_FUNC
11700Sstevel@tonic-gate
11710Sstevel@tonic-gate'NEXTKEY' => <<'END_OF_FUNC',
11720Sstevel@tonic-gatesub NEXTKEY {
11730Sstevel@tonic-gate    $_[0]->{'.parameters'}->[$_[0]->{'.iterator'}++];
11740Sstevel@tonic-gate}
11750Sstevel@tonic-gateEND_OF_FUNC
11760Sstevel@tonic-gate
11770Sstevel@tonic-gate'EXISTS' => <<'END_OF_FUNC',
11780Sstevel@tonic-gatesub EXISTS {
11790Sstevel@tonic-gate    exists $_[0]->{$_[1]};
11800Sstevel@tonic-gate}
11810Sstevel@tonic-gateEND_OF_FUNC
11820Sstevel@tonic-gate
11830Sstevel@tonic-gate'DELETE' => <<'END_OF_FUNC',
11840Sstevel@tonic-gatesub DELETE {
11850Sstevel@tonic-gate    $_[0]->delete($_[1]);
11860Sstevel@tonic-gate}
11870Sstevel@tonic-gateEND_OF_FUNC
11880Sstevel@tonic-gate
11890Sstevel@tonic-gate'CLEAR' => <<'END_OF_FUNC',
11900Sstevel@tonic-gatesub CLEAR {
11910Sstevel@tonic-gate    %{$_[0]}=();
11920Sstevel@tonic-gate}
11930Sstevel@tonic-gate####
11940Sstevel@tonic-gateEND_OF_FUNC
11950Sstevel@tonic-gate
11960Sstevel@tonic-gate####
11970Sstevel@tonic-gate# Append a new value to an existing query
11980Sstevel@tonic-gate####
11990Sstevel@tonic-gate'append' => <<'EOF',
12000Sstevel@tonic-gatesub append {
1201667Sps156622    my($self,@p) = self_or_default(@_);
12020Sstevel@tonic-gate    my($name,$value) = rearrange([NAME,[VALUE,VALUES]],@p);
12030Sstevel@tonic-gate    my(@values) = defined($value) ? (ref($value) ? @{$value} : $value) : ();
12040Sstevel@tonic-gate    if (@values) {
12050Sstevel@tonic-gate	$self->add_parameter($name);
12060Sstevel@tonic-gate	push(@{$self->{$name}},@values);
12070Sstevel@tonic-gate    }
12080Sstevel@tonic-gate    return $self->param($name);
12090Sstevel@tonic-gate}
12100Sstevel@tonic-gateEOF
12110Sstevel@tonic-gate
12120Sstevel@tonic-gate#### Method: delete_all
12130Sstevel@tonic-gate# Delete all parameters
12140Sstevel@tonic-gate####
12150Sstevel@tonic-gate'delete_all' => <<'EOF',
12160Sstevel@tonic-gatesub delete_all {
12170Sstevel@tonic-gate    my($self) = self_or_default(@_);
12180Sstevel@tonic-gate    my @param = $self->param();
12190Sstevel@tonic-gate    $self->delete(@param);
12200Sstevel@tonic-gate}
12210Sstevel@tonic-gateEOF
12220Sstevel@tonic-gate
12230Sstevel@tonic-gate'Delete' => <<'EOF',
12240Sstevel@tonic-gatesub Delete {
12250Sstevel@tonic-gate    my($self,@p) = self_or_default(@_);
12260Sstevel@tonic-gate    $self->delete(@p);
12270Sstevel@tonic-gate}
12280Sstevel@tonic-gateEOF
12290Sstevel@tonic-gate
12300Sstevel@tonic-gate'Delete_all' => <<'EOF',
12310Sstevel@tonic-gatesub Delete_all {
12320Sstevel@tonic-gate    my($self,@p) = self_or_default(@_);
12330Sstevel@tonic-gate    $self->delete_all(@p);
12340Sstevel@tonic-gate}
12350Sstevel@tonic-gateEOF
12360Sstevel@tonic-gate
12370Sstevel@tonic-gate#### Method: autoescape
12380Sstevel@tonic-gate# If you want to turn off the autoescaping features,
12390Sstevel@tonic-gate# call this method with undef as the argument
12400Sstevel@tonic-gate'autoEscape' => <<'END_OF_FUNC',
12410Sstevel@tonic-gatesub autoEscape {
12420Sstevel@tonic-gate    my($self,$escape) = self_or_default(@_);
12430Sstevel@tonic-gate    my $d = $self->{'escape'};
12440Sstevel@tonic-gate    $self->{'escape'} = $escape;
12450Sstevel@tonic-gate    $d;
12460Sstevel@tonic-gate}
12470Sstevel@tonic-gateEND_OF_FUNC
12480Sstevel@tonic-gate
12490Sstevel@tonic-gate
12500Sstevel@tonic-gate#### Method: version
12510Sstevel@tonic-gate# Return the current version
12520Sstevel@tonic-gate####
12530Sstevel@tonic-gate'version' => <<'END_OF_FUNC',
12540Sstevel@tonic-gatesub version {
12550Sstevel@tonic-gate    return $VERSION;
12560Sstevel@tonic-gate}
12570Sstevel@tonic-gateEND_OF_FUNC
12580Sstevel@tonic-gate
12590Sstevel@tonic-gate#### Method: url_param
12600Sstevel@tonic-gate# Return a parameter in the QUERY_STRING, regardless of
12610Sstevel@tonic-gate# whether this was a POST or a GET
12620Sstevel@tonic-gate####
12630Sstevel@tonic-gate'url_param' => <<'END_OF_FUNC',
12640Sstevel@tonic-gatesub url_param {
12650Sstevel@tonic-gate    my ($self,@p) = self_or_default(@_);
12660Sstevel@tonic-gate    my $name = shift(@p);
12670Sstevel@tonic-gate    return undef unless exists($ENV{QUERY_STRING});
12680Sstevel@tonic-gate    unless (exists($self->{'.url_param'})) {
12690Sstevel@tonic-gate	$self->{'.url_param'}={}; # empty hash
12700Sstevel@tonic-gate	if ($ENV{QUERY_STRING} =~ /=/) {
12710Sstevel@tonic-gate	    my(@pairs) = split(/[&;]/,$ENV{QUERY_STRING});
12720Sstevel@tonic-gate	    my($param,$value);
12730Sstevel@tonic-gate	    foreach (@pairs) {
12740Sstevel@tonic-gate		($param,$value) = split('=',$_,2);
12750Sstevel@tonic-gate		$param = unescape($param);
12760Sstevel@tonic-gate		$value = unescape($value);
12770Sstevel@tonic-gate		push(@{$self->{'.url_param'}->{$param}},$value);
12780Sstevel@tonic-gate	    }
12790Sstevel@tonic-gate	} else {
12800Sstevel@tonic-gate	    $self->{'.url_param'}->{'keywords'} = [$self->parse_keywordlist($ENV{QUERY_STRING})];
12810Sstevel@tonic-gate	}
12820Sstevel@tonic-gate    }
12830Sstevel@tonic-gate    return keys %{$self->{'.url_param'}} unless defined($name);
12840Sstevel@tonic-gate    return () unless $self->{'.url_param'}->{$name};
12850Sstevel@tonic-gate    return wantarray ? @{$self->{'.url_param'}->{$name}}
12860Sstevel@tonic-gate                     : $self->{'.url_param'}->{$name}->[0];
12870Sstevel@tonic-gate}
12880Sstevel@tonic-gateEND_OF_FUNC
12890Sstevel@tonic-gate
12900Sstevel@tonic-gate#### Method: Dump
12910Sstevel@tonic-gate# Returns a string in which all the known parameter/value
12920Sstevel@tonic-gate# pairs are represented as nested lists, mainly for the purposes
12930Sstevel@tonic-gate# of debugging.
12940Sstevel@tonic-gate####
12950Sstevel@tonic-gate'Dump' => <<'END_OF_FUNC',
12960Sstevel@tonic-gatesub Dump {
12970Sstevel@tonic-gate    my($self) = self_or_default(@_);
12980Sstevel@tonic-gate    my($param,$value,@result);
12990Sstevel@tonic-gate    return '<ul></ul>' unless $self->param;
13000Sstevel@tonic-gate    push(@result,"<ul>");
13010Sstevel@tonic-gate    foreach $param ($self->param) {
13020Sstevel@tonic-gate	my($name)=$self->escapeHTML($param);
13030Sstevel@tonic-gate	push(@result,"<li><strong>$param</strong></li>");
13040Sstevel@tonic-gate	push(@result,"<ul>");
13050Sstevel@tonic-gate	foreach $value ($self->param($param)) {
13060Sstevel@tonic-gate	    $value = $self->escapeHTML($value);
13070Sstevel@tonic-gate            $value =~ s/\n/<br \/>\n/g;
13080Sstevel@tonic-gate	    push(@result,"<li>$value</li>");
13090Sstevel@tonic-gate	}
13100Sstevel@tonic-gate	push(@result,"</ul>");
13110Sstevel@tonic-gate    }
13120Sstevel@tonic-gate    push(@result,"</ul>");
13130Sstevel@tonic-gate    return join("\n",@result);
13140Sstevel@tonic-gate}
13150Sstevel@tonic-gateEND_OF_FUNC
13160Sstevel@tonic-gate
13170Sstevel@tonic-gate#### Method as_string
13180Sstevel@tonic-gate#
13190Sstevel@tonic-gate# synonym for "dump"
13200Sstevel@tonic-gate####
13210Sstevel@tonic-gate'as_string' => <<'END_OF_FUNC',
13220Sstevel@tonic-gatesub as_string {
13230Sstevel@tonic-gate    &Dump(@_);
13240Sstevel@tonic-gate}
13250Sstevel@tonic-gateEND_OF_FUNC
13260Sstevel@tonic-gate
13270Sstevel@tonic-gate#### Method: save
13280Sstevel@tonic-gate# Write values out to a filehandle in such a way that they can
13290Sstevel@tonic-gate# be reinitialized by the filehandle form of the new() method
13300Sstevel@tonic-gate####
13310Sstevel@tonic-gate'save' => <<'END_OF_FUNC',
13320Sstevel@tonic-gatesub save {
13330Sstevel@tonic-gate    my($self,$filehandle) = self_or_default(@_);
13340Sstevel@tonic-gate    $filehandle = to_filehandle($filehandle);
13350Sstevel@tonic-gate    my($param);
13360Sstevel@tonic-gate    local($,) = '';  # set print field separator back to a sane value
13370Sstevel@tonic-gate    local($\) = '';  # set output line separator to a sane value
13380Sstevel@tonic-gate    foreach $param ($self->param) {
13390Sstevel@tonic-gate	my($escaped_param) = escape($param);
13400Sstevel@tonic-gate	my($value);
13410Sstevel@tonic-gate	foreach $value ($self->param($param)) {
13420Sstevel@tonic-gate	    print $filehandle "$escaped_param=",escape("$value"),"\n";
13430Sstevel@tonic-gate	}
13440Sstevel@tonic-gate    }
13450Sstevel@tonic-gate    foreach (keys %{$self->{'.fieldnames'}}) {
13460Sstevel@tonic-gate          print $filehandle ".cgifields=",escape("$_"),"\n";
13470Sstevel@tonic-gate    }
13480Sstevel@tonic-gate    print $filehandle "=\n";    # end of record
13490Sstevel@tonic-gate}
13500Sstevel@tonic-gateEND_OF_FUNC
13510Sstevel@tonic-gate
13520Sstevel@tonic-gate
13530Sstevel@tonic-gate#### Method: save_parameters
13540Sstevel@tonic-gate# An alias for save() that is a better name for exportation.
13550Sstevel@tonic-gate# Only intended to be used with the function (non-OO) interface.
13560Sstevel@tonic-gate####
13570Sstevel@tonic-gate'save_parameters' => <<'END_OF_FUNC',
13580Sstevel@tonic-gatesub save_parameters {
13590Sstevel@tonic-gate    my $fh = shift;
13600Sstevel@tonic-gate    return save(to_filehandle($fh));
13610Sstevel@tonic-gate}
13620Sstevel@tonic-gateEND_OF_FUNC
13630Sstevel@tonic-gate
13640Sstevel@tonic-gate#### Method: restore_parameters
13650Sstevel@tonic-gate# A way to restore CGI parameters from an initializer.
13660Sstevel@tonic-gate# Only intended to be used with the function (non-OO) interface.
13670Sstevel@tonic-gate####
13680Sstevel@tonic-gate'restore_parameters' => <<'END_OF_FUNC',
13690Sstevel@tonic-gatesub restore_parameters {
13700Sstevel@tonic-gate    $Q = $CGI::DefaultClass->new(@_);
13710Sstevel@tonic-gate}
13720Sstevel@tonic-gateEND_OF_FUNC
13730Sstevel@tonic-gate
13740Sstevel@tonic-gate#### Method: multipart_init
13750Sstevel@tonic-gate# Return a Content-Type: style header for server-push
13760Sstevel@tonic-gate# This has to be NPH on most web servers, and it is advisable to set $| = 1
13770Sstevel@tonic-gate#
13780Sstevel@tonic-gate# Many thanks to Ed Jordan <ed@fidalgo.net> for this
13790Sstevel@tonic-gate# contribution, updated by Andrew Benham (adsb@bigfoot.com)
13800Sstevel@tonic-gate####
13810Sstevel@tonic-gate'multipart_init' => <<'END_OF_FUNC',
13820Sstevel@tonic-gatesub multipart_init {
13830Sstevel@tonic-gate    my($self,@p) = self_or_default(@_);
13840Sstevel@tonic-gate    my($boundary,@other) = rearrange([BOUNDARY],@p);
13850Sstevel@tonic-gate    $boundary = $boundary || '------- =_aaaaaaaaaa0';
13860Sstevel@tonic-gate    $self->{'separator'} = "$CRLF--$boundary$CRLF";
13870Sstevel@tonic-gate    $self->{'final_separator'} = "$CRLF--$boundary--$CRLF";
13880Sstevel@tonic-gate    $type = SERVER_PUSH($boundary);
13890Sstevel@tonic-gate    return $self->header(
1390667Sps156622	-nph => 0,
13910Sstevel@tonic-gate	-type => $type,
13920Sstevel@tonic-gate	(map { split "=", $_, 2 } @other),
13930Sstevel@tonic-gate    ) . "WARNING: YOUR BROWSER DOESN'T SUPPORT THIS SERVER-PUSH TECHNOLOGY." . $self->multipart_end;
13940Sstevel@tonic-gate}
13950Sstevel@tonic-gateEND_OF_FUNC
13960Sstevel@tonic-gate
13970Sstevel@tonic-gate
13980Sstevel@tonic-gate#### Method: multipart_start
13990Sstevel@tonic-gate# Return a Content-Type: style header for server-push, start of section
14000Sstevel@tonic-gate#
14010Sstevel@tonic-gate# Many thanks to Ed Jordan <ed@fidalgo.net> for this
14020Sstevel@tonic-gate# contribution, updated by Andrew Benham (adsb@bigfoot.com)
14030Sstevel@tonic-gate####
14040Sstevel@tonic-gate'multipart_start' => <<'END_OF_FUNC',
14050Sstevel@tonic-gatesub multipart_start {
14060Sstevel@tonic-gate    my(@header);
14070Sstevel@tonic-gate    my($self,@p) = self_or_default(@_);
14080Sstevel@tonic-gate    my($type,@other) = rearrange([TYPE],@p);
14090Sstevel@tonic-gate    $type = $type || 'text/html';
14100Sstevel@tonic-gate    push(@header,"Content-Type: $type");
14110Sstevel@tonic-gate
14120Sstevel@tonic-gate    # rearrange() was designed for the HTML portion, so we
14130Sstevel@tonic-gate    # need to fix it up a little.
14140Sstevel@tonic-gate    foreach (@other) {
14150Sstevel@tonic-gate        # Don't use \s because of perl bug 21951
14160Sstevel@tonic-gate        next unless my($header,$value) = /([^ \r\n\t=]+)=\"?(.+?)\"?$/;
14170Sstevel@tonic-gate	($_ = $header) =~ s/^(\w)(.*)/$1 . lc ($2) . ': '.$self->unescapeHTML($value)/e;
14180Sstevel@tonic-gate    }
14190Sstevel@tonic-gate    push(@header,@other);
14200Sstevel@tonic-gate    my $header = join($CRLF,@header)."${CRLF}${CRLF}";
14210Sstevel@tonic-gate    return $header;
14220Sstevel@tonic-gate}
14230Sstevel@tonic-gateEND_OF_FUNC
14240Sstevel@tonic-gate
14250Sstevel@tonic-gate
14260Sstevel@tonic-gate#### Method: multipart_end
14270Sstevel@tonic-gate# Return a MIME boundary separator for server-push, end of section
14280Sstevel@tonic-gate#
14290Sstevel@tonic-gate# Many thanks to Ed Jordan <ed@fidalgo.net> for this
14300Sstevel@tonic-gate# contribution
14310Sstevel@tonic-gate####
14320Sstevel@tonic-gate'multipart_end' => <<'END_OF_FUNC',
14330Sstevel@tonic-gatesub multipart_end {
14340Sstevel@tonic-gate    my($self,@p) = self_or_default(@_);
14350Sstevel@tonic-gate    return $self->{'separator'};
14360Sstevel@tonic-gate}
14370Sstevel@tonic-gateEND_OF_FUNC
14380Sstevel@tonic-gate
14390Sstevel@tonic-gate
14400Sstevel@tonic-gate#### Method: multipart_final
14410Sstevel@tonic-gate# Return a MIME boundary separator for server-push, end of all sections
14420Sstevel@tonic-gate#
14430Sstevel@tonic-gate# Contributed by Andrew Benham (adsb@bigfoot.com)
14440Sstevel@tonic-gate####
14450Sstevel@tonic-gate'multipart_final' => <<'END_OF_FUNC',
14460Sstevel@tonic-gatesub multipart_final {
14470Sstevel@tonic-gate    my($self,@p) = self_or_default(@_);
14480Sstevel@tonic-gate    return $self->{'final_separator'} . "WARNING: YOUR BROWSER DOESN'T SUPPORT THIS SERVER-PUSH TECHNOLOGY." . $CRLF;
14490Sstevel@tonic-gate}
14500Sstevel@tonic-gateEND_OF_FUNC
14510Sstevel@tonic-gate
14520Sstevel@tonic-gate
14530Sstevel@tonic-gate#### Method: header
14540Sstevel@tonic-gate# Return a Content-Type: style header
14550Sstevel@tonic-gate#
14560Sstevel@tonic-gate####
14570Sstevel@tonic-gate'header' => <<'END_OF_FUNC',
14580Sstevel@tonic-gatesub header {
14590Sstevel@tonic-gate    my($self,@p) = self_or_default(@_);
14600Sstevel@tonic-gate    my(@header);
14610Sstevel@tonic-gate
14620Sstevel@tonic-gate    return "" if $self->{'.header_printed'}++ and $HEADERS_ONCE;
14630Sstevel@tonic-gate
14640Sstevel@tonic-gate    my($type,$status,$cookie,$target,$expires,$nph,$charset,$attachment,$p3p,@other) =
14650Sstevel@tonic-gate	rearrange([['TYPE','CONTENT_TYPE','CONTENT-TYPE'],
14660Sstevel@tonic-gate			    'STATUS',['COOKIE','COOKIES'],'TARGET',
14670Sstevel@tonic-gate                            'EXPIRES','NPH','CHARSET',
14680Sstevel@tonic-gate                            'ATTACHMENT','P3P'],@p);
14690Sstevel@tonic-gate
14700Sstevel@tonic-gate    $nph     ||= $NPH;
1471*6287Sps156622
1472*6287Sps156622    $type ||= 'text/html' unless defined($type);
1473*6287Sps156622
14740Sstevel@tonic-gate    if (defined $charset) {
14750Sstevel@tonic-gate      $self->charset($charset);
14760Sstevel@tonic-gate    } else {
1477*6287Sps156622      $charset = $self->charset if $type =~ /^text\//;
14780Sstevel@tonic-gate    }
1479*6287Sps156622   $charset ||= '';
14800Sstevel@tonic-gate
14810Sstevel@tonic-gate    # rearrange() was designed for the HTML portion, so we
14820Sstevel@tonic-gate    # need to fix it up a little.
14830Sstevel@tonic-gate    foreach (@other) {
14840Sstevel@tonic-gate        # Don't use \s because of perl bug 21951
14850Sstevel@tonic-gate        next unless my($header,$value) = /([^ \r\n\t=]+)=\"?(.+?)\"?$/;
14860Sstevel@tonic-gate        ($_ = $header) =~ s/^(\w)(.*)/"\u$1\L$2" . ': '.$self->unescapeHTML($value)/e;
14870Sstevel@tonic-gate    }
14880Sstevel@tonic-gate
1489*6287Sps156622    $type .= "; charset=$charset"
1490*6287Sps156622      if     $type ne ''
1491*6287Sps156622         and $type !~ /\bcharset\b/
1492*6287Sps156622         and defined $charset
1493*6287Sps156622         and $charset ne '';
14940Sstevel@tonic-gate
14950Sstevel@tonic-gate    # Maybe future compatibility.  Maybe not.
14960Sstevel@tonic-gate    my $protocol = $ENV{SERVER_PROTOCOL} || 'HTTP/1.0';
14970Sstevel@tonic-gate    push(@header,$protocol . ' ' . ($status || '200 OK')) if $nph;
14980Sstevel@tonic-gate    push(@header,"Server: " . &server_software()) if $nph;
14990Sstevel@tonic-gate
15000Sstevel@tonic-gate    push(@header,"Status: $status") if $status;
15010Sstevel@tonic-gate    push(@header,"Window-Target: $target") if $target;
15020Sstevel@tonic-gate    if ($p3p) {
15030Sstevel@tonic-gate       $p3p = join ' ',@$p3p if ref($p3p) eq 'ARRAY';
15040Sstevel@tonic-gate       push(@header,qq(P3P: policyref="/w3c/p3p.xml", CP="$p3p"));
15050Sstevel@tonic-gate    }
15060Sstevel@tonic-gate    # push all the cookies -- there may be several
15070Sstevel@tonic-gate    if ($cookie) {
15080Sstevel@tonic-gate	my(@cookie) = ref($cookie) && ref($cookie) eq 'ARRAY' ? @{$cookie} : $cookie;
15090Sstevel@tonic-gate	foreach (@cookie) {
15100Sstevel@tonic-gate            my $cs = UNIVERSAL::isa($_,'CGI::Cookie') ? $_->as_string : $_;
15110Sstevel@tonic-gate	    push(@header,"Set-Cookie: $cs") if $cs ne '';
15120Sstevel@tonic-gate	}
15130Sstevel@tonic-gate    }
15140Sstevel@tonic-gate    # if the user indicates an expiration time, then we need
15150Sstevel@tonic-gate    # both an Expires and a Date header (so that the browser is
15160Sstevel@tonic-gate    # uses OUR clock)
15170Sstevel@tonic-gate    push(@header,"Expires: " . expires($expires,'http'))
15180Sstevel@tonic-gate	if $expires;
15190Sstevel@tonic-gate    push(@header,"Date: " . expires(0,'http')) if $expires || $cookie || $nph;
15200Sstevel@tonic-gate    push(@header,"Pragma: no-cache") if $self->cache();
15210Sstevel@tonic-gate    push(@header,"Content-Disposition: attachment; filename=\"$attachment\"") if $attachment;
15220Sstevel@tonic-gate    push(@header,map {ucfirst $_} @other);
15230Sstevel@tonic-gate    push(@header,"Content-Type: $type") if $type ne '';
15240Sstevel@tonic-gate    my $header = join($CRLF,@header)."${CRLF}${CRLF}";
1525*6287Sps156622    if (($MOD_PERL >= 1) && !$nph) {
15260Sstevel@tonic-gate        $self->r->send_cgi_header($header);
15270Sstevel@tonic-gate        return '';
15280Sstevel@tonic-gate    }
15290Sstevel@tonic-gate    return $header;
15300Sstevel@tonic-gate}
15310Sstevel@tonic-gateEND_OF_FUNC
15320Sstevel@tonic-gate
15330Sstevel@tonic-gate
15340Sstevel@tonic-gate#### Method: cache
15350Sstevel@tonic-gate# Control whether header() will produce the no-cache
15360Sstevel@tonic-gate# Pragma directive.
15370Sstevel@tonic-gate####
15380Sstevel@tonic-gate'cache' => <<'END_OF_FUNC',
15390Sstevel@tonic-gatesub cache {
15400Sstevel@tonic-gate    my($self,$new_value) = self_or_default(@_);
15410Sstevel@tonic-gate    $new_value = '' unless $new_value;
15420Sstevel@tonic-gate    if ($new_value ne '') {
15430Sstevel@tonic-gate	$self->{'cache'} = $new_value;
15440Sstevel@tonic-gate    }
15450Sstevel@tonic-gate    return $self->{'cache'};
15460Sstevel@tonic-gate}
15470Sstevel@tonic-gateEND_OF_FUNC
15480Sstevel@tonic-gate
15490Sstevel@tonic-gate
15500Sstevel@tonic-gate#### Method: redirect
15510Sstevel@tonic-gate# Return a Location: style header
15520Sstevel@tonic-gate#
15530Sstevel@tonic-gate####
15540Sstevel@tonic-gate'redirect' => <<'END_OF_FUNC',
15550Sstevel@tonic-gatesub redirect {
15560Sstevel@tonic-gate    my($self,@p) = self_or_default(@_);
1557667Sps156622    my($url,$target,$status,$cookie,$nph,@other) =
1558667Sps156622         rearrange([[LOCATION,URI,URL],TARGET,STATUS,['COOKIE','COOKIES'],NPH],@p);
1559*6287Sps156622    $status = '302 Found' unless defined $status;
15600Sstevel@tonic-gate    $url ||= $self->self_url;
15610Sstevel@tonic-gate    my(@o);
15620Sstevel@tonic-gate    foreach (@other) { tr/\"//d; push(@o,split("=",$_,2)); }
15630Sstevel@tonic-gate    unshift(@o,
1564667Sps156622	 '-Status'  => $status,
15650Sstevel@tonic-gate	 '-Location'=> $url,
15660Sstevel@tonic-gate	 '-nph'     => $nph);
15670Sstevel@tonic-gate    unshift(@o,'-Target'=>$target) if $target;
15680Sstevel@tonic-gate    unshift(@o,'-Type'=>'');
15690Sstevel@tonic-gate    my @unescaped;
15700Sstevel@tonic-gate    unshift(@unescaped,'-Cookie'=>$cookie) if $cookie;
15710Sstevel@tonic-gate    return $self->header((map {$self->unescapeHTML($_)} @o),@unescaped);
15720Sstevel@tonic-gate}
15730Sstevel@tonic-gateEND_OF_FUNC
15740Sstevel@tonic-gate
15750Sstevel@tonic-gate
15760Sstevel@tonic-gate#### Method: start_html
15770Sstevel@tonic-gate# Canned HTML header
15780Sstevel@tonic-gate#
15790Sstevel@tonic-gate# Parameters:
15800Sstevel@tonic-gate# $title -> (optional) The title for this HTML document (-title)
15810Sstevel@tonic-gate# $author -> (optional) e-mail address of the author (-author)
15820Sstevel@tonic-gate# $base -> (optional) if set to true, will enter the BASE address of this document
15830Sstevel@tonic-gate#          for resolving relative references (-base)
15840Sstevel@tonic-gate# $xbase -> (optional) alternative base at some remote location (-xbase)
15850Sstevel@tonic-gate# $target -> (optional) target window to load all links into (-target)
15860Sstevel@tonic-gate# $script -> (option) Javascript code (-script)
15870Sstevel@tonic-gate# $no_script -> (option) Javascript <noscript> tag (-noscript)
15880Sstevel@tonic-gate# $meta -> (optional) Meta information tags
15890Sstevel@tonic-gate# $head -> (optional) any other elements you'd like to incorporate into the <head> tag
15900Sstevel@tonic-gate#           (a scalar or array ref)
15910Sstevel@tonic-gate# $style -> (optional) reference to an external style sheet
15920Sstevel@tonic-gate# @other -> (optional) any other named parameters you'd like to incorporate into
15930Sstevel@tonic-gate#           the <body> tag.
15940Sstevel@tonic-gate####
15950Sstevel@tonic-gate'start_html' => <<'END_OF_FUNC',
15960Sstevel@tonic-gatesub start_html {
15970Sstevel@tonic-gate    my($self,@p) = &self_or_default(@_);
15980Sstevel@tonic-gate    my($title,$author,$base,$xbase,$script,$noscript,
1599667Sps156622        $target,$meta,$head,$style,$dtd,$lang,$encoding,$declare_xml,@other) =
1600667Sps156622	rearrange([TITLE,AUTHOR,BASE,XBASE,SCRIPT,NOSCRIPT,TARGET,
1601667Sps156622                   META,HEAD,STYLE,DTD,LANG,ENCODING,DECLARE_XML],@p);
1602667Sps156622
1603667Sps156622    $self->element_id(0);
1604667Sps156622    $self->element_tab(0);
16050Sstevel@tonic-gate
1606*6287Sps156622    $encoding = lc($self->charset) unless defined $encoding;
16070Sstevel@tonic-gate
1608667Sps156622    # Need to sort out the DTD before it's okay to call escapeHTML().
16090Sstevel@tonic-gate    my(@result,$xml_dtd);
16100Sstevel@tonic-gate    if ($dtd) {
16110Sstevel@tonic-gate        if (defined(ref($dtd)) and (ref($dtd) eq 'ARRAY')) {
16120Sstevel@tonic-gate            $dtd = $DEFAULT_DTD unless $dtd->[0] =~ m|^-//|;
16130Sstevel@tonic-gate        } else {
16140Sstevel@tonic-gate            $dtd = $DEFAULT_DTD unless $dtd =~ m|^-//|;
16150Sstevel@tonic-gate        }
16160Sstevel@tonic-gate    } else {
16170Sstevel@tonic-gate        $dtd = $XHTML ? XHTML_DTD : $DEFAULT_DTD;
16180Sstevel@tonic-gate    }
16190Sstevel@tonic-gate
16200Sstevel@tonic-gate    $xml_dtd++ if ref($dtd) eq 'ARRAY' && $dtd->[0] =~ /\bXHTML\b/i;
16210Sstevel@tonic-gate    $xml_dtd++ if ref($dtd) eq '' && $dtd =~ /\bXHTML\b/i;
1622667Sps156622    push @result,qq(<?xml version="1.0" encoding="$encoding"?>) if $xml_dtd && $declare_xml;
16230Sstevel@tonic-gate
16240Sstevel@tonic-gate    if (ref($dtd) && ref($dtd) eq 'ARRAY') {
16250Sstevel@tonic-gate        push(@result,qq(<!DOCTYPE html\n\tPUBLIC "$dtd->[0]"\n\t "$dtd->[1]">));
1626667Sps156622	$DTD_PUBLIC_IDENTIFIER = $dtd->[0];
16270Sstevel@tonic-gate    } else {
16280Sstevel@tonic-gate        push(@result,qq(<!DOCTYPE html\n\tPUBLIC "$dtd">));
1629667Sps156622	$DTD_PUBLIC_IDENTIFIER = $dtd;
16300Sstevel@tonic-gate    }
1631667Sps156622
1632667Sps156622    # Now that we know whether we're using the HTML 3.2 DTD or not, it's okay to
1633667Sps156622    # call escapeHTML().  Strangely enough, the title needs to be escaped as
1634667Sps156622    # HTML while the author needs to be escaped as a URL.
1635667Sps156622    $title = $self->escapeHTML($title || 'Untitled Document');
1636667Sps156622    $author = $self->escape($author);
1637667Sps156622
1638667Sps156622    if ($DTD_PUBLIC_IDENTIFIER =~ /[^X]HTML (2\.0|3\.2)/i) {
1639667Sps156622	$lang = "" unless defined $lang;
1640667Sps156622	$XHTML = 0;
1641667Sps156622    }
1642667Sps156622    else {
1643667Sps156622	$lang = 'en-US' unless defined $lang;
1644667Sps156622    }
1645667Sps156622
1646667Sps156622    my $lang_bits = $lang ne '' ? qq( lang="$lang" xml:lang="$lang") : '';
1647667Sps156622    my $meta_bits = qq(<meta http-equiv="Content-Type" content="text/html; charset=$encoding" />)
1648667Sps156622                    if $XHTML && $encoding && !$declare_xml;
1649667Sps156622
1650667Sps156622    push(@result,$XHTML ? qq(<html xmlns="http://www.w3.org/1999/xhtml"$lang_bits>\n<head>\n<title>$title</title>)
1651667Sps156622                        : ($lang ? qq(<html lang="$lang">) : "<html>")
16520Sstevel@tonic-gate	                  . "<head><title>$title</title>");
16530Sstevel@tonic-gate	if (defined $author) {
16540Sstevel@tonic-gate    push(@result,$XHTML ? "<link rev=\"made\" href=\"mailto:$author\" />"
1655667Sps156622			: "<link rev=\"made\" href=\"mailto:$author\">");
16560Sstevel@tonic-gate	}
16570Sstevel@tonic-gate
16580Sstevel@tonic-gate    if ($base || $xbase || $target) {
16590Sstevel@tonic-gate	my $href = $xbase || $self->url('-path'=>1);
16600Sstevel@tonic-gate	my $t = $target ? qq/ target="$target"/ : '';
16610Sstevel@tonic-gate	push(@result,$XHTML ? qq(<base href="$href"$t />) : qq(<base href="$href"$t>));
16620Sstevel@tonic-gate    }
16630Sstevel@tonic-gate
16640Sstevel@tonic-gate    if ($meta && ref($meta) && (ref($meta) eq 'HASH')) {
16650Sstevel@tonic-gate	foreach (keys %$meta) { push(@result,$XHTML ? qq(<meta name="$_" content="$meta->{$_}" />)
16660Sstevel@tonic-gate			: qq(<meta name="$_" content="$meta->{$_}">)); }
16670Sstevel@tonic-gate    }
16680Sstevel@tonic-gate
16690Sstevel@tonic-gate    push(@result,ref($head) ? @$head : $head) if $head;
16700Sstevel@tonic-gate
16710Sstevel@tonic-gate    # handle the infrequently-used -style and -script parameters
1672667Sps156622    push(@result,$self->_style($style))   if defined $style;
16730Sstevel@tonic-gate    push(@result,$self->_script($script)) if defined $script;
1674667Sps156622    push(@result,$meta_bits)              if defined $meta_bits;
16750Sstevel@tonic-gate
16760Sstevel@tonic-gate    # handle -noscript parameter
16770Sstevel@tonic-gate    push(@result,<<END) if $noscript;
16780Sstevel@tonic-gate<noscript>
16790Sstevel@tonic-gate$noscript
16800Sstevel@tonic-gate</noscript>
16810Sstevel@tonic-gateEND
16820Sstevel@tonic-gate    ;
16830Sstevel@tonic-gate    my($other) = @other ? " @other" : '';
1684667Sps156622    push(@result,"</head>\n<body$other>\n");
16850Sstevel@tonic-gate    return join("\n",@result);
16860Sstevel@tonic-gate}
16870Sstevel@tonic-gateEND_OF_FUNC
16880Sstevel@tonic-gate
16890Sstevel@tonic-gate### Method: _style
16900Sstevel@tonic-gate# internal method for generating a CSS style section
16910Sstevel@tonic-gate####
16920Sstevel@tonic-gate'_style' => <<'END_OF_FUNC',
16930Sstevel@tonic-gatesub _style {
16940Sstevel@tonic-gate    my ($self,$style) = @_;
16950Sstevel@tonic-gate    my (@result);
1696*6287Sps156622
16970Sstevel@tonic-gate    my $type = 'text/css';
1698*6287Sps156622    my $rel  = 'stylesheet';
1699*6287Sps156622
17000Sstevel@tonic-gate
17010Sstevel@tonic-gate    my $cdata_start = $XHTML ? "\n<!--/* <![CDATA[ */" : "\n<!-- ";
17020Sstevel@tonic-gate    my $cdata_end   = $XHTML ? "\n/* ]]> */-->\n" : " -->\n";
17030Sstevel@tonic-gate
1704667Sps156622    my @s = ref($style) eq 'ARRAY' ? @$style : $style;
1705*6287Sps156622    my $other = '';
1706667Sps156622
1707667Sps156622    for my $s (@s) {
1708667Sps156622      if (ref($s)) {
1709*6287Sps156622       my($src,$code,$verbatim,$stype,$alternate,$foo,@other) =
1710*6287Sps156622           rearrange([qw(SRC CODE VERBATIM TYPE ALTERNATE FOO)],
1711667Sps156622                      ('-foo'=>'bar',
1712667Sps156622                       ref($s) eq 'ARRAY' ? @$s : %$s));
1713*6287Sps156622       my $type = defined $stype ? $stype : 'text/css';
1714*6287Sps156622       my $rel  = $alternate ? 'alternate stylesheet' : 'stylesheet';
1715*6287Sps156622       $other = "@other" if @other;
1716667Sps156622
1717667Sps156622       if (ref($src) eq "ARRAY") # Check to see if the $src variable is an array reference
1718667Sps156622       { # If it is, push a LINK tag for each one
1719667Sps156622           foreach $src (@$src)
1720667Sps156622         {
1721*6287Sps156622           push(@result,$XHTML ? qq(<link rel="$rel" type="$type" href="$src" $other/>)
1722*6287Sps156622                             : qq(<link rel="$rel" type="$type" href="$src"$other>)) if $src;
1723667Sps156622         }
17240Sstevel@tonic-gate       }
1725667Sps156622       else
1726667Sps156622       { # Otherwise, push the single -src, if it exists.
1727*6287Sps156622         push(@result,$XHTML ? qq(<link rel="$rel" type="$type" href="$src" $other/>)
1728*6287Sps156622                             : qq(<link rel="$rel" type="$type" href="$src"$other>)
1729667Sps156622              ) if $src;
1730667Sps156622        }
1731667Sps156622     if ($verbatim) {
1732667Sps156622           my @v = ref($verbatim) eq 'ARRAY' ? @$verbatim : $verbatim;
1733667Sps156622           push(@result, "<style type=\"text/css\">\n$_\n</style>") foreach @v;
17340Sstevel@tonic-gate      }
1735667Sps156622      my @c = ref($code) eq 'ARRAY' ? @$code : $code if $code;
1736667Sps156622      push(@result,style({'type'=>$type},"$cdata_start\n$_\n$cdata_end")) foreach @c;
1737667Sps156622
1738667Sps156622      } else {
1739667Sps156622           my $src = $s;
1740*6287Sps156622           push(@result,$XHTML ? qq(<link rel="$rel" type="$type" href="$src" $other/>)
1741*6287Sps156622                               : qq(<link rel="$rel" type="$type" href="$src"$other>));
1742667Sps156622      }
17430Sstevel@tonic-gate    }
17440Sstevel@tonic-gate    @result;
17450Sstevel@tonic-gate}
17460Sstevel@tonic-gateEND_OF_FUNC
17470Sstevel@tonic-gate
17480Sstevel@tonic-gate'_script' => <<'END_OF_FUNC',
17490Sstevel@tonic-gatesub _script {
17500Sstevel@tonic-gate    my ($self,$script) = @_;
17510Sstevel@tonic-gate    my (@result);
17520Sstevel@tonic-gate
17530Sstevel@tonic-gate    my (@scripts) = ref($script) eq 'ARRAY' ? @$script : ($script);
17540Sstevel@tonic-gate    foreach $script (@scripts) {
17550Sstevel@tonic-gate	my($src,$code,$language);
17560Sstevel@tonic-gate	if (ref($script)) { # script is a hash
1757*6287Sps156622	    ($src,$code,$type) =
1758*6287Sps156622		rearrange(['SRC','CODE',['LANGUAGE','TYPE']],
17590Sstevel@tonic-gate				 '-foo'=>'bar',	# a trick to allow the '-' to be omitted
17600Sstevel@tonic-gate				 ref($script) eq 'ARRAY' ? @$script : %$script);
1761*6287Sps156622            $type ||= 'text/javascript';
1762*6287Sps156622            unless ($type =~ m!\w+/\w+!) {
1763*6287Sps156622                $type =~ s/[\d.]+$//;
1764*6287Sps156622                $type = "text/$type";
17650Sstevel@tonic-gate            }
17660Sstevel@tonic-gate	} else {
1767*6287Sps156622	    ($src,$code,$type) = ('',$script, 'text/javascript');
17680Sstevel@tonic-gate	}
17690Sstevel@tonic-gate
17700Sstevel@tonic-gate    my $comment = '//';  # javascript by default
17710Sstevel@tonic-gate    $comment = '#' if $type=~/perl|tcl/i;
17720Sstevel@tonic-gate    $comment = "'" if $type=~/vbscript/i;
17730Sstevel@tonic-gate
17740Sstevel@tonic-gate    my ($cdata_start,$cdata_end);
17750Sstevel@tonic-gate    if ($XHTML) {
17760Sstevel@tonic-gate       $cdata_start    = "$comment<![CDATA[\n";
17770Sstevel@tonic-gate       $cdata_end     .= "\n$comment]]>";
17780Sstevel@tonic-gate    } else {
17790Sstevel@tonic-gate       $cdata_start  =  "\n<!-- Hide script\n";
17800Sstevel@tonic-gate       $cdata_end    = $comment;
17810Sstevel@tonic-gate       $cdata_end   .= " End script hiding -->\n";
17820Sstevel@tonic-gate   }
17830Sstevel@tonic-gate     my(@satts);
17840Sstevel@tonic-gate     push(@satts,'src'=>$src) if $src;
17850Sstevel@tonic-gate     push(@satts,'type'=>$type);
1786667Sps156622     $code = $cdata_start . $code . $cdata_end if defined $code;
1787667Sps156622     push(@result,$self->script({@satts},$code || ''));
17880Sstevel@tonic-gate    }
17890Sstevel@tonic-gate    @result;
17900Sstevel@tonic-gate}
17910Sstevel@tonic-gateEND_OF_FUNC
17920Sstevel@tonic-gate
17930Sstevel@tonic-gate#### Method: end_html
17940Sstevel@tonic-gate# End an HTML document.
17950Sstevel@tonic-gate# Trivial method for completeness.  Just returns "</body>"
17960Sstevel@tonic-gate####
17970Sstevel@tonic-gate'end_html' => <<'END_OF_FUNC',
17980Sstevel@tonic-gatesub end_html {
1799667Sps156622    return "\n</body>\n</html>";
18000Sstevel@tonic-gate}
18010Sstevel@tonic-gateEND_OF_FUNC
18020Sstevel@tonic-gate
18030Sstevel@tonic-gate
18040Sstevel@tonic-gate################################
18050Sstevel@tonic-gate# METHODS USED IN BUILDING FORMS
18060Sstevel@tonic-gate################################
18070Sstevel@tonic-gate
18080Sstevel@tonic-gate#### Method: isindex
18090Sstevel@tonic-gate# Just prints out the isindex tag.
18100Sstevel@tonic-gate# Parameters:
18110Sstevel@tonic-gate#  $action -> optional URL of script to run
18120Sstevel@tonic-gate# Returns:
18130Sstevel@tonic-gate#   A string containing a <isindex> tag
18140Sstevel@tonic-gate'isindex' => <<'END_OF_FUNC',
18150Sstevel@tonic-gatesub isindex {
18160Sstevel@tonic-gate    my($self,@p) = self_or_default(@_);
18170Sstevel@tonic-gate    my($action,@other) = rearrange([ACTION],@p);
18180Sstevel@tonic-gate    $action = qq/ action="$action"/ if $action;
18190Sstevel@tonic-gate    my($other) = @other ? " @other" : '';
18200Sstevel@tonic-gate    return $XHTML ? "<isindex$action$other />" : "<isindex$action$other>";
18210Sstevel@tonic-gate}
18220Sstevel@tonic-gateEND_OF_FUNC
18230Sstevel@tonic-gate
18240Sstevel@tonic-gate
18250Sstevel@tonic-gate#### Method: startform
18260Sstevel@tonic-gate# Start a form
18270Sstevel@tonic-gate# Parameters:
18280Sstevel@tonic-gate#   $method -> optional submission method to use (GET or POST)
18290Sstevel@tonic-gate#   $action -> optional URL of script to run
18300Sstevel@tonic-gate#   $enctype ->encoding to use (URL_ENCODED or MULTIPART)
18310Sstevel@tonic-gate'startform' => <<'END_OF_FUNC',
18320Sstevel@tonic-gatesub startform {
18330Sstevel@tonic-gate    my($self,@p) = self_or_default(@_);
18340Sstevel@tonic-gate
18350Sstevel@tonic-gate    my($method,$action,$enctype,@other) =
18360Sstevel@tonic-gate	rearrange([METHOD,ACTION,ENCTYPE],@p);
18370Sstevel@tonic-gate
1838667Sps156622    $method  = $self->escapeHTML(lc($method) || 'post');
1839667Sps156622    $enctype = $self->escapeHTML($enctype || &URL_ENCODED);
1840667Sps156622    if (defined $action) {
1841667Sps156622       $action = $self->escapeHTML($action);
1842667Sps156622    }
1843667Sps156622    else {
1844*6287Sps156622       $action = $self->escapeHTML($self->request_uri || $self->self_url);
18450Sstevel@tonic-gate    }
18460Sstevel@tonic-gate    $action = qq(action="$action");
18470Sstevel@tonic-gate    my($other) = @other ? " @other" : '';
18480Sstevel@tonic-gate    $self->{'.parametersToAdd'}={};
18490Sstevel@tonic-gate    return qq/<form method="$method" $action enctype="$enctype"$other>\n/;
18500Sstevel@tonic-gate}
18510Sstevel@tonic-gateEND_OF_FUNC
18520Sstevel@tonic-gate
18530Sstevel@tonic-gate
18540Sstevel@tonic-gate#### Method: start_form
18550Sstevel@tonic-gate# synonym for startform
18560Sstevel@tonic-gate'start_form' => <<'END_OF_FUNC',
18570Sstevel@tonic-gatesub start_form {
1858667Sps156622    $XHTML ? &start_multipart_form : &startform;
18590Sstevel@tonic-gate}
18600Sstevel@tonic-gateEND_OF_FUNC
18610Sstevel@tonic-gate
18620Sstevel@tonic-gate'end_multipart_form' => <<'END_OF_FUNC',
18630Sstevel@tonic-gatesub end_multipart_form {
18640Sstevel@tonic-gate    &endform;
18650Sstevel@tonic-gate}
18660Sstevel@tonic-gateEND_OF_FUNC
18670Sstevel@tonic-gate
18680Sstevel@tonic-gate#### Method: start_multipart_form
18690Sstevel@tonic-gate# synonym for startform
18700Sstevel@tonic-gate'start_multipart_form' => <<'END_OF_FUNC',
18710Sstevel@tonic-gatesub start_multipart_form {
18720Sstevel@tonic-gate    my($self,@p) = self_or_default(@_);
1873*6287Sps156622    if (defined($p[0]) && substr($p[0],0,1) eq '-') {
1874*6287Sps156622      return $self->startform(-enctype=>&MULTIPART,@p);
18750Sstevel@tonic-gate    } else {
18760Sstevel@tonic-gate	my($method,$action,@other) =
18770Sstevel@tonic-gate	    rearrange([METHOD,ACTION],@p);
18780Sstevel@tonic-gate	return $self->startform($method,$action,&MULTIPART,@other);
18790Sstevel@tonic-gate    }
18800Sstevel@tonic-gate}
18810Sstevel@tonic-gateEND_OF_FUNC
18820Sstevel@tonic-gate
18830Sstevel@tonic-gate
18840Sstevel@tonic-gate#### Method: endform
18850Sstevel@tonic-gate# End a form
18860Sstevel@tonic-gate'endform' => <<'END_OF_FUNC',
18870Sstevel@tonic-gatesub endform {
1888*6287Sps156622    my($self,@p) = self_or_default(@_);
18890Sstevel@tonic-gate    if ( $NOSTICKY ) {
18900Sstevel@tonic-gate    return wantarray ? ("</form>") : "\n</form>";
18910Sstevel@tonic-gate    } else {
1892*6287Sps156622      if (my @fields = $self->get_fields) {
1893*6287Sps156622         return wantarray ? ("<div>",@fields,"</div>","</form>")
1894*6287Sps156622                          : "<div>".(join '',@fields)."</div>\n</form>";
1895*6287Sps156622      } else {
1896*6287Sps156622         return "</form>";
1897*6287Sps156622      }
18980Sstevel@tonic-gate    }
18990Sstevel@tonic-gate}
19000Sstevel@tonic-gateEND_OF_FUNC
19010Sstevel@tonic-gate
19020Sstevel@tonic-gate
19030Sstevel@tonic-gate'_textfield' => <<'END_OF_FUNC',
19040Sstevel@tonic-gatesub _textfield {
19050Sstevel@tonic-gate    my($self,$tag,@p) = self_or_default(@_);
1906667Sps156622    my($name,$default,$size,$maxlength,$override,$tabindex,@other) =
1907667Sps156622	rearrange([NAME,[DEFAULT,VALUE,VALUES],SIZE,MAXLENGTH,[OVERRIDE,FORCE],TABINDEX],@p);
19080Sstevel@tonic-gate
19090Sstevel@tonic-gate    my $current = $override ? $default :
19100Sstevel@tonic-gate	(defined($self->param($name)) ? $self->param($name) : $default);
19110Sstevel@tonic-gate
19120Sstevel@tonic-gate    $current = defined($current) ? $self->escapeHTML($current,1) : '';
19130Sstevel@tonic-gate    $name = defined($name) ? $self->escapeHTML($name) : '';
19140Sstevel@tonic-gate    my($s) = defined($size) ? qq/ size="$size"/ : '';
19150Sstevel@tonic-gate    my($m) = defined($maxlength) ? qq/ maxlength="$maxlength"/ : '';
19160Sstevel@tonic-gate    my($other) = @other ? " @other" : '';
19170Sstevel@tonic-gate    # this entered at cristy's request to fix problems with file upload fields
19180Sstevel@tonic-gate    # and WebTV -- not sure it won't break stuff
19190Sstevel@tonic-gate    my($value) = $current ne '' ? qq(value="$current") : '';
1920667Sps156622    $tabindex = $self->element_tab($tabindex);
1921*6287Sps156622    return $XHTML ? qq(<input type="$tag" name="$name" $tabindex$value$s$m$other />)
19220Sstevel@tonic-gate                  : qq(<input type="$tag" name="$name" $value$s$m$other>);
19230Sstevel@tonic-gate}
19240Sstevel@tonic-gateEND_OF_FUNC
19250Sstevel@tonic-gate
19260Sstevel@tonic-gate#### Method: textfield
19270Sstevel@tonic-gate# Parameters:
19280Sstevel@tonic-gate#   $name -> Name of the text field
19290Sstevel@tonic-gate#   $default -> Optional default value of the field if not
19300Sstevel@tonic-gate#                already defined.
19310Sstevel@tonic-gate#   $size ->  Optional width of field in characaters.
19320Sstevel@tonic-gate#   $maxlength -> Optional maximum number of characters.
19330Sstevel@tonic-gate# Returns:
19340Sstevel@tonic-gate#   A string containing a <input type="text"> field
19350Sstevel@tonic-gate#
19360Sstevel@tonic-gate'textfield' => <<'END_OF_FUNC',
19370Sstevel@tonic-gatesub textfield {
19380Sstevel@tonic-gate    my($self,@p) = self_or_default(@_);
19390Sstevel@tonic-gate    $self->_textfield('text',@p);
19400Sstevel@tonic-gate}
19410Sstevel@tonic-gateEND_OF_FUNC
19420Sstevel@tonic-gate
19430Sstevel@tonic-gate
19440Sstevel@tonic-gate#### Method: filefield
19450Sstevel@tonic-gate# Parameters:
19460Sstevel@tonic-gate#   $name -> Name of the file upload field
19470Sstevel@tonic-gate#   $size ->  Optional width of field in characaters.
19480Sstevel@tonic-gate#   $maxlength -> Optional maximum number of characters.
19490Sstevel@tonic-gate# Returns:
19500Sstevel@tonic-gate#   A string containing a <input type="file"> field
19510Sstevel@tonic-gate#
19520Sstevel@tonic-gate'filefield' => <<'END_OF_FUNC',
19530Sstevel@tonic-gatesub filefield {
19540Sstevel@tonic-gate    my($self,@p) = self_or_default(@_);
19550Sstevel@tonic-gate    $self->_textfield('file',@p);
19560Sstevel@tonic-gate}
19570Sstevel@tonic-gateEND_OF_FUNC
19580Sstevel@tonic-gate
19590Sstevel@tonic-gate
19600Sstevel@tonic-gate#### Method: password
19610Sstevel@tonic-gate# Create a "secret password" entry field
19620Sstevel@tonic-gate# Parameters:
19630Sstevel@tonic-gate#   $name -> Name of the field
19640Sstevel@tonic-gate#   $default -> Optional default value of the field if not
19650Sstevel@tonic-gate#                already defined.
19660Sstevel@tonic-gate#   $size ->  Optional width of field in characters.
19670Sstevel@tonic-gate#   $maxlength -> Optional maximum characters that can be entered.
19680Sstevel@tonic-gate# Returns:
19690Sstevel@tonic-gate#   A string containing a <input type="password"> field
19700Sstevel@tonic-gate#
19710Sstevel@tonic-gate'password_field' => <<'END_OF_FUNC',
19720Sstevel@tonic-gatesub password_field {
19730Sstevel@tonic-gate    my ($self,@p) = self_or_default(@_);
19740Sstevel@tonic-gate    $self->_textfield('password',@p);
19750Sstevel@tonic-gate}
19760Sstevel@tonic-gateEND_OF_FUNC
19770Sstevel@tonic-gate
19780Sstevel@tonic-gate#### Method: textarea
19790Sstevel@tonic-gate# Parameters:
19800Sstevel@tonic-gate#   $name -> Name of the text field
19810Sstevel@tonic-gate#   $default -> Optional default value of the field if not
19820Sstevel@tonic-gate#                already defined.
19830Sstevel@tonic-gate#   $rows ->  Optional number of rows in text area
19840Sstevel@tonic-gate#   $columns -> Optional number of columns in text area
19850Sstevel@tonic-gate# Returns:
19860Sstevel@tonic-gate#   A string containing a <textarea></textarea> tag
19870Sstevel@tonic-gate#
19880Sstevel@tonic-gate'textarea' => <<'END_OF_FUNC',
19890Sstevel@tonic-gatesub textarea {
19900Sstevel@tonic-gate    my($self,@p) = self_or_default(@_);
1991667Sps156622    my($name,$default,$rows,$cols,$override,$tabindex,@other) =
1992667Sps156622	rearrange([NAME,[DEFAULT,VALUE],ROWS,[COLS,COLUMNS],[OVERRIDE,FORCE],TABINDEX],@p);
19930Sstevel@tonic-gate
19940Sstevel@tonic-gate    my($current)= $override ? $default :
19950Sstevel@tonic-gate	(defined($self->param($name)) ? $self->param($name) : $default);
19960Sstevel@tonic-gate
19970Sstevel@tonic-gate    $name = defined($name) ? $self->escapeHTML($name) : '';
19980Sstevel@tonic-gate    $current = defined($current) ? $self->escapeHTML($current) : '';
19990Sstevel@tonic-gate    my($r) = $rows ? qq/ rows="$rows"/ : '';
20000Sstevel@tonic-gate    my($c) = $cols ? qq/ cols="$cols"/ : '';
20010Sstevel@tonic-gate    my($other) = @other ? " @other" : '';
2002667Sps156622    $tabindex = $self->element_tab($tabindex);
2003*6287Sps156622    return qq{<textarea name="$name" $tabindex$r$c$other>$current</textarea>};
20040Sstevel@tonic-gate}
20050Sstevel@tonic-gateEND_OF_FUNC
20060Sstevel@tonic-gate
20070Sstevel@tonic-gate
20080Sstevel@tonic-gate#### Method: button
20090Sstevel@tonic-gate# Create a javascript button.
20100Sstevel@tonic-gate# Parameters:
20110Sstevel@tonic-gate#   $name ->  (optional) Name for the button. (-name)
20120Sstevel@tonic-gate#   $value -> (optional) Value of the button when selected (and visible name) (-value)
20130Sstevel@tonic-gate#   $onclick -> (optional) Text of the JavaScript to run when the button is
20140Sstevel@tonic-gate#                clicked.
20150Sstevel@tonic-gate# Returns:
20160Sstevel@tonic-gate#   A string containing a <input type="button"> tag
20170Sstevel@tonic-gate####
20180Sstevel@tonic-gate'button' => <<'END_OF_FUNC',
20190Sstevel@tonic-gatesub button {
20200Sstevel@tonic-gate    my($self,@p) = self_or_default(@_);
20210Sstevel@tonic-gate
2022667Sps156622    my($label,$value,$script,$tabindex,@other) = rearrange([NAME,[VALUE,LABEL],
2023667Sps156622						            [ONCLICK,SCRIPT],TABINDEX],@p);
20240Sstevel@tonic-gate
20250Sstevel@tonic-gate    $label=$self->escapeHTML($label);
20260Sstevel@tonic-gate    $value=$self->escapeHTML($value,1);
20270Sstevel@tonic-gate    $script=$self->escapeHTML($script);
20280Sstevel@tonic-gate
20290Sstevel@tonic-gate    my($name) = '';
20300Sstevel@tonic-gate    $name = qq/ name="$label"/ if $label;
20310Sstevel@tonic-gate    $value = $value || $label;
20320Sstevel@tonic-gate    my($val) = '';
20330Sstevel@tonic-gate    $val = qq/ value="$value"/ if $value;
20340Sstevel@tonic-gate    $script = qq/ onclick="$script"/ if $script;
20350Sstevel@tonic-gate    my($other) = @other ? " @other" : '';
2036667Sps156622    $tabindex = $self->element_tab($tabindex);
2037*6287Sps156622    return $XHTML ? qq(<input type="button" $tabindex$name$val$script$other />)
20380Sstevel@tonic-gate                  : qq(<input type="button"$name$val$script$other>);
20390Sstevel@tonic-gate}
20400Sstevel@tonic-gateEND_OF_FUNC
20410Sstevel@tonic-gate
20420Sstevel@tonic-gate
20430Sstevel@tonic-gate#### Method: submit
20440Sstevel@tonic-gate# Create a "submit query" button.
20450Sstevel@tonic-gate# Parameters:
20460Sstevel@tonic-gate#   $name ->  (optional) Name for the button.
20470Sstevel@tonic-gate#   $value -> (optional) Value of the button when selected (also doubles as label).
20480Sstevel@tonic-gate#   $label -> (optional) Label printed on the button(also doubles as the value).
20490Sstevel@tonic-gate# Returns:
20500Sstevel@tonic-gate#   A string containing a <input type="submit"> tag
20510Sstevel@tonic-gate####
20520Sstevel@tonic-gate'submit' => <<'END_OF_FUNC',
20530Sstevel@tonic-gatesub submit {
20540Sstevel@tonic-gate    my($self,@p) = self_or_default(@_);
20550Sstevel@tonic-gate
2056667Sps156622    my($label,$value,$tabindex,@other) = rearrange([NAME,[VALUE,LABEL],TABINDEX],@p);
20570Sstevel@tonic-gate
20580Sstevel@tonic-gate    $label=$self->escapeHTML($label);
20590Sstevel@tonic-gate    $value=$self->escapeHTML($value,1);
20600Sstevel@tonic-gate
2061*6287Sps156622    my $name = $NOSTICKY ? '' : 'name=".submit" ';
2062*6287Sps156622    $name = qq/name="$label" / if defined($label);
20630Sstevel@tonic-gate    $value = defined($value) ? $value : $label;
20640Sstevel@tonic-gate    my $val = '';
2065*6287Sps156622    $val = qq/value="$value" / if defined($value);
2066667Sps156622    $tabindex = $self->element_tab($tabindex);
2067*6287Sps156622    my($other) = @other ? "@other " : '';
2068*6287Sps156622    return $XHTML ? qq(<input type="submit" $tabindex$name$val$other/>)
2069*6287Sps156622                  : qq(<input type="submit" $name$val$other>);
20700Sstevel@tonic-gate}
20710Sstevel@tonic-gateEND_OF_FUNC
20720Sstevel@tonic-gate
20730Sstevel@tonic-gate
20740Sstevel@tonic-gate#### Method: reset
20750Sstevel@tonic-gate# Create a "reset" button.
20760Sstevel@tonic-gate# Parameters:
20770Sstevel@tonic-gate#   $name -> (optional) Name for the button.
20780Sstevel@tonic-gate# Returns:
20790Sstevel@tonic-gate#   A string containing a <input type="reset"> tag
20800Sstevel@tonic-gate####
20810Sstevel@tonic-gate'reset' => <<'END_OF_FUNC',
20820Sstevel@tonic-gatesub reset {
20830Sstevel@tonic-gate    my($self,@p) = self_or_default(@_);
2084667Sps156622    my($label,$value,$tabindex,@other) = rearrange(['NAME',['VALUE','LABEL'],TABINDEX],@p);
20850Sstevel@tonic-gate    $label=$self->escapeHTML($label);
20860Sstevel@tonic-gate    $value=$self->escapeHTML($value,1);
20870Sstevel@tonic-gate    my ($name) = ' name=".reset"';
20880Sstevel@tonic-gate    $name = qq/ name="$label"/ if defined($label);
20890Sstevel@tonic-gate    $value = defined($value) ? $value : $label;
20900Sstevel@tonic-gate    my($val) = '';
20910Sstevel@tonic-gate    $val = qq/ value="$value"/ if defined($value);
20920Sstevel@tonic-gate    my($other) = @other ? " @other" : '';
2093667Sps156622    $tabindex = $self->element_tab($tabindex);
2094*6287Sps156622    return $XHTML ? qq(<input type="reset" $tabindex$name$val$other />)
20950Sstevel@tonic-gate                  : qq(<input type="reset"$name$val$other>);
20960Sstevel@tonic-gate}
20970Sstevel@tonic-gateEND_OF_FUNC
20980Sstevel@tonic-gate
20990Sstevel@tonic-gate
21000Sstevel@tonic-gate#### Method: defaults
21010Sstevel@tonic-gate# Create a "defaults" button.
21020Sstevel@tonic-gate# Parameters:
21030Sstevel@tonic-gate#   $name -> (optional) Name for the button.
21040Sstevel@tonic-gate# Returns:
21050Sstevel@tonic-gate#   A string containing a <input type="submit" name=".defaults"> tag
21060Sstevel@tonic-gate#
21070Sstevel@tonic-gate# Note: this button has a special meaning to the initialization script,
21080Sstevel@tonic-gate# and tells it to ERASE the current query string so that your defaults
21090Sstevel@tonic-gate# are used again!
21100Sstevel@tonic-gate####
21110Sstevel@tonic-gate'defaults' => <<'END_OF_FUNC',
21120Sstevel@tonic-gatesub defaults {
21130Sstevel@tonic-gate    my($self,@p) = self_or_default(@_);
21140Sstevel@tonic-gate
2115667Sps156622    my($label,$tabindex,@other) = rearrange([[NAME,VALUE],TABINDEX],@p);
21160Sstevel@tonic-gate
21170Sstevel@tonic-gate    $label=$self->escapeHTML($label,1);
21180Sstevel@tonic-gate    $label = $label || "Defaults";
21190Sstevel@tonic-gate    my($value) = qq/ value="$label"/;
21200Sstevel@tonic-gate    my($other) = @other ? " @other" : '';
2121667Sps156622    $tabindex = $self->element_tab($tabindex);
2122*6287Sps156622    return $XHTML ? qq(<input type="submit" name=".defaults" $tabindex$value$other />)
21230Sstevel@tonic-gate                  : qq/<input type="submit" NAME=".defaults"$value$other>/;
21240Sstevel@tonic-gate}
21250Sstevel@tonic-gateEND_OF_FUNC
21260Sstevel@tonic-gate
21270Sstevel@tonic-gate
21280Sstevel@tonic-gate#### Method: comment
21290Sstevel@tonic-gate# Create an HTML <!-- comment -->
21300Sstevel@tonic-gate# Parameters: a string
21310Sstevel@tonic-gate'comment' => <<'END_OF_FUNC',
21320Sstevel@tonic-gatesub comment {
21330Sstevel@tonic-gate    my($self,@p) = self_or_CGI(@_);
21340Sstevel@tonic-gate    return "<!-- @p -->";
21350Sstevel@tonic-gate}
21360Sstevel@tonic-gateEND_OF_FUNC
21370Sstevel@tonic-gate
21380Sstevel@tonic-gate#### Method: checkbox
21390Sstevel@tonic-gate# Create a checkbox that is not logically linked to any others.
21400Sstevel@tonic-gate# The field value is "on" when the button is checked.
21410Sstevel@tonic-gate# Parameters:
21420Sstevel@tonic-gate#   $name -> Name of the checkbox
21430Sstevel@tonic-gate#   $checked -> (optional) turned on by default if true
21440Sstevel@tonic-gate#   $value -> (optional) value of the checkbox, 'on' by default
21450Sstevel@tonic-gate#   $label -> (optional) a user-readable label printed next to the box.
21460Sstevel@tonic-gate#             Otherwise the checkbox name is used.
21470Sstevel@tonic-gate# Returns:
21480Sstevel@tonic-gate#   A string containing a <input type="checkbox"> field
21490Sstevel@tonic-gate####
21500Sstevel@tonic-gate'checkbox' => <<'END_OF_FUNC',
21510Sstevel@tonic-gatesub checkbox {
21520Sstevel@tonic-gate    my($self,@p) = self_or_default(@_);
21530Sstevel@tonic-gate
2154*6287Sps156622    my($name,$checked,$value,$label,$labelattributes,$override,$tabindex,@other) =
2155*6287Sps156622       rearrange([NAME,[CHECKED,SELECTED,ON],VALUE,LABEL,LABELATTRIBUTES,
2156*6287Sps156622                   [OVERRIDE,FORCE],TABINDEX],@p);
2157667Sps156622
21580Sstevel@tonic-gate    $value = defined $value ? $value : 'on';
21590Sstevel@tonic-gate
21600Sstevel@tonic-gate    if (!$override && ($self->{'.fieldnames'}->{$name} ||
21610Sstevel@tonic-gate		       defined $self->param($name))) {
21620Sstevel@tonic-gate	$checked = grep($_ eq $value,$self->param($name)) ? $self->_checked(1) : '';
21630Sstevel@tonic-gate    } else {
21640Sstevel@tonic-gate	$checked = $self->_checked($checked);
21650Sstevel@tonic-gate    }
21660Sstevel@tonic-gate    my($the_label) = defined $label ? $label : $name;
21670Sstevel@tonic-gate    $name = $self->escapeHTML($name);
21680Sstevel@tonic-gate    $value = $self->escapeHTML($value,1);
21690Sstevel@tonic-gate    $the_label = $self->escapeHTML($the_label);
2170*6287Sps156622    my($other) = @other ? "@other " : '';
2171667Sps156622    $tabindex = $self->element_tab($tabindex);
21720Sstevel@tonic-gate    $self->register_parameter($name);
2173*6287Sps156622    return $XHTML ? CGI::label($labelattributes,
2174*6287Sps156622                    qq{<input type="checkbox" name="$name" value="$value" $tabindex$checked$other/>$the_label})
21750Sstevel@tonic-gate                  : qq{<input type="checkbox" name="$name" value="$value"$checked$other>$the_label};
21760Sstevel@tonic-gate}
21770Sstevel@tonic-gateEND_OF_FUNC
21780Sstevel@tonic-gate
21790Sstevel@tonic-gate
21800Sstevel@tonic-gate
21810Sstevel@tonic-gate# Escape HTML -- used internally
21820Sstevel@tonic-gate'escapeHTML' => <<'END_OF_FUNC',
21830Sstevel@tonic-gatesub escapeHTML {
21840Sstevel@tonic-gate         # hack to work around  earlier hacks
21850Sstevel@tonic-gate         push @_,$_[0] if @_==1 && $_[0] eq 'CGI';
21860Sstevel@tonic-gate         my ($self,$toencode,$newlinestoo) = CGI::self_or_default(@_);
21870Sstevel@tonic-gate         return undef unless defined($toencode);
21880Sstevel@tonic-gate         return $toencode if ref($self) && !$self->{'escape'};
21890Sstevel@tonic-gate         $toencode =~ s{&}{&amp;}gso;
21900Sstevel@tonic-gate         $toencode =~ s{<}{&lt;}gso;
21910Sstevel@tonic-gate         $toencode =~ s{>}{&gt;}gso;
2192667Sps156622	 if ($DTD_PUBLIC_IDENTIFIER =~ /[^X]HTML 3\.2/i) {
2193667Sps156622	     # $quot; was accidentally omitted from the HTML 3.2 DTD -- see
2194667Sps156622	     # <http://validator.w3.org/docs/errors.html#bad-entity> /
2195667Sps156622	     # <http://lists.w3.org/Archives/Public/www-html/1997Mar/0003.html>.
2196667Sps156622	     $toencode =~ s{"}{&#34;}gso;
2197667Sps156622         }
2198667Sps156622         else {
2199667Sps156622	     $toencode =~ s{"}{&quot;}gso;
2200667Sps156622         }
22010Sstevel@tonic-gate         my $latin = uc $self->{'.charset'} eq 'ISO-8859-1' ||
22020Sstevel@tonic-gate                     uc $self->{'.charset'} eq 'WINDOWS-1252';
22030Sstevel@tonic-gate         if ($latin) {  # bug in some browsers
22040Sstevel@tonic-gate                $toencode =~ s{'}{&#39;}gso;
22050Sstevel@tonic-gate                $toencode =~ s{\x8b}{&#8249;}gso;
22060Sstevel@tonic-gate                $toencode =~ s{\x9b}{&#8250;}gso;
22070Sstevel@tonic-gate                if (defined $newlinestoo && $newlinestoo) {
22080Sstevel@tonic-gate                     $toencode =~ s{\012}{&#10;}gso;
22090Sstevel@tonic-gate                     $toencode =~ s{\015}{&#13;}gso;
22100Sstevel@tonic-gate                }
22110Sstevel@tonic-gate         }
22120Sstevel@tonic-gate         return $toencode;
22130Sstevel@tonic-gate}
22140Sstevel@tonic-gateEND_OF_FUNC
22150Sstevel@tonic-gate
22160Sstevel@tonic-gate# unescape HTML -- used internally
22170Sstevel@tonic-gate'unescapeHTML' => <<'END_OF_FUNC',
22180Sstevel@tonic-gatesub unescapeHTML {
22190Sstevel@tonic-gate    # hack to work around  earlier hacks
22200Sstevel@tonic-gate    push @_,$_[0] if @_==1 && $_[0] eq 'CGI';
22210Sstevel@tonic-gate    my ($self,$string) = CGI::self_or_default(@_);
22220Sstevel@tonic-gate    return undef unless defined($string);
22230Sstevel@tonic-gate    my $latin = defined $self->{'.charset'} ? $self->{'.charset'} =~ /^(ISO-8859-1|WINDOWS-1252)$/i
22240Sstevel@tonic-gate                                            : 1;
22250Sstevel@tonic-gate    # thanks to Randal Schwartz for the correct solution to this one
22260Sstevel@tonic-gate    $string=~ s[&(.*?);]{
22270Sstevel@tonic-gate	local $_ = $1;
22280Sstevel@tonic-gate	/^amp$/i	? "&" :
22290Sstevel@tonic-gate	/^quot$/i	? '"' :
22300Sstevel@tonic-gate        /^gt$/i		? ">" :
22310Sstevel@tonic-gate	/^lt$/i		? "<" :
22320Sstevel@tonic-gate	/^#(\d+)$/ && $latin	     ? chr($1) :
22330Sstevel@tonic-gate	/^#x([0-9a-f]+)$/i && $latin ? chr(hex($1)) :
22340Sstevel@tonic-gate	$_
22350Sstevel@tonic-gate	}gex;
22360Sstevel@tonic-gate    return $string;
22370Sstevel@tonic-gate}
22380Sstevel@tonic-gateEND_OF_FUNC
22390Sstevel@tonic-gate
22400Sstevel@tonic-gate# Internal procedure - don't use
22410Sstevel@tonic-gate'_tableize' => <<'END_OF_FUNC',
22420Sstevel@tonic-gatesub _tableize {
22430Sstevel@tonic-gate    my($rows,$columns,$rowheaders,$colheaders,@elements) = @_;
2244667Sps156622    my @rowheaders = $rowheaders ? @$rowheaders : ();
2245667Sps156622    my @colheaders = $colheaders ? @$colheaders : ();
22460Sstevel@tonic-gate    my($result);
22470Sstevel@tonic-gate
22480Sstevel@tonic-gate    if (defined($columns)) {
22490Sstevel@tonic-gate	$rows = int(0.99 + @elements/$columns) unless defined($rows);
22500Sstevel@tonic-gate    }
22510Sstevel@tonic-gate    if (defined($rows)) {
22520Sstevel@tonic-gate	$columns = int(0.99 + @elements/$rows) unless defined($columns);
22530Sstevel@tonic-gate    }
2254667Sps156622
22550Sstevel@tonic-gate    # rearrange into a pretty table
22560Sstevel@tonic-gate    $result = "<table>";
22570Sstevel@tonic-gate    my($row,$column);
2258667Sps156622    unshift(@colheaders,'') if @colheaders && @rowheaders;
2259667Sps156622    $result .= "<tr>" if @colheaders;
2260667Sps156622    foreach (@colheaders) {
22610Sstevel@tonic-gate	$result .= "<th>$_</th>";
22620Sstevel@tonic-gate    }
22630Sstevel@tonic-gate    for ($row=0;$row<$rows;$row++) {
22640Sstevel@tonic-gate	$result .= "<tr>";
2265667Sps156622	$result .= "<th>$rowheaders[$row]</th>" if @rowheaders;
22660Sstevel@tonic-gate	for ($column=0;$column<$columns;$column++) {
22670Sstevel@tonic-gate	    $result .= "<td>" . $elements[$column*$rows + $row] . "</td>"
22680Sstevel@tonic-gate		if defined($elements[$column*$rows + $row]);
22690Sstevel@tonic-gate	}
22700Sstevel@tonic-gate	$result .= "</tr>";
22710Sstevel@tonic-gate    }
22720Sstevel@tonic-gate    $result .= "</table>";
22730Sstevel@tonic-gate    return $result;
22740Sstevel@tonic-gate}
22750Sstevel@tonic-gateEND_OF_FUNC
22760Sstevel@tonic-gate
22770Sstevel@tonic-gate
22780Sstevel@tonic-gate#### Method: radio_group
22790Sstevel@tonic-gate# Create a list of logically-linked radio buttons.
22800Sstevel@tonic-gate# Parameters:
22810Sstevel@tonic-gate#   $name -> Common name for all the buttons.
22820Sstevel@tonic-gate#   $values -> A pointer to a regular array containing the
22830Sstevel@tonic-gate#             values for each button in the group.
22840Sstevel@tonic-gate#   $default -> (optional) Value of the button to turn on by default.  Pass '-'
22850Sstevel@tonic-gate#               to turn _nothing_ on.
22860Sstevel@tonic-gate#   $linebreak -> (optional) Set to true to place linebreaks
22870Sstevel@tonic-gate#             between the buttons.
22880Sstevel@tonic-gate#   $labels -> (optional)
22890Sstevel@tonic-gate#             A pointer to an associative array of labels to print next to each checkbox
22900Sstevel@tonic-gate#             in the form $label{'value'}="Long explanatory label".
22910Sstevel@tonic-gate#             Otherwise the provided values are used as the labels.
22920Sstevel@tonic-gate# Returns:
22930Sstevel@tonic-gate#   An ARRAY containing a series of <input type="radio"> fields
22940Sstevel@tonic-gate####
22950Sstevel@tonic-gate'radio_group' => <<'END_OF_FUNC',
22960Sstevel@tonic-gatesub radio_group {
22970Sstevel@tonic-gate    my($self,@p) = self_or_default(@_);
2298667Sps156622   $self->_box_group('radio',@p);
2299667Sps156622}
2300667Sps156622END_OF_FUNC
2301667Sps156622
2302667Sps156622#### Method: checkbox_group
2303667Sps156622# Create a list of logically-linked checkboxes.
2304667Sps156622# Parameters:
2305667Sps156622#   $name -> Common name for all the check boxes
2306667Sps156622#   $values -> A pointer to a regular array containing the
2307667Sps156622#             values for each checkbox in the group.
2308667Sps156622#   $defaults -> (optional)
2309667Sps156622#             1. If a pointer to a regular array of checkbox values,
2310667Sps156622#             then this will be used to decide which
2311667Sps156622#             checkboxes to turn on by default.
2312667Sps156622#             2. If a scalar, will be assumed to hold the
2313667Sps156622#             value of a single checkbox in the group to turn on.
2314667Sps156622#   $linebreak -> (optional) Set to true to place linebreaks
2315667Sps156622#             between the buttons.
2316667Sps156622#   $labels -> (optional)
2317667Sps156622#             A pointer to an associative array of labels to print next to each checkbox
2318667Sps156622#             in the form $label{'value'}="Long explanatory label".
2319667Sps156622#             Otherwise the provided values are used as the labels.
2320667Sps156622# Returns:
2321667Sps156622#   An ARRAY containing a series of <input type="checkbox"> fields
2322667Sps156622####
2323667Sps156622
2324667Sps156622'checkbox_group' => <<'END_OF_FUNC',
2325667Sps156622sub checkbox_group {
2326667Sps156622    my($self,@p) = self_or_default(@_);
2327667Sps156622   $self->_box_group('checkbox',@p);
2328667Sps156622}
2329667Sps156622END_OF_FUNC
2330667Sps156622
2331667Sps156622'_box_group' => <<'END_OF_FUNC',
2332667Sps156622sub _box_group {
2333667Sps156622    my $self     = shift;
2334667Sps156622    my $box_type = shift;
2335667Sps156622
2336*6287Sps156622    my($name,$values,$defaults,$linebreak,$labels,$labelattributes,
2337*6287Sps156622       $attributes,$rows,$columns,$rowheaders,$colheaders,
2338*6287Sps156622       $override,$nolabels,$tabindex,$disabled,@other) =
2339*6287Sps156622        rearrange([NAME,[VALUES,VALUE],[DEFAULT,DEFAULTS],LINEBREAK,LABELS,LABELATTRIBUTES,
2340*6287Sps156622                       ATTRIBUTES,ROWS,[COLUMNS,COLS],[ROWHEADERS,ROWHEADER],[COLHEADERS,COLHEADER],
2341*6287Sps156622                       [OVERRIDE,FORCE],NOLABELS,TABINDEX,DISABLED
2342*6287Sps156622                  ],@_);
2343*6287Sps156622
2344*6287Sps156622
2345*6287Sps156622    my($result,$checked,@elements,@values);
2346*6287Sps156622
23470Sstevel@tonic-gate    @values = $self->_set_values_and_labels($values,\$labels,$name);
2348667Sps156622    my %checked = $self->previous_or_default($name,$defaults,$override);
23490Sstevel@tonic-gate
23500Sstevel@tonic-gate    # If no check array is specified, check the first by default
2351667Sps156622    $checked{$values[0]}++ if $box_type eq 'radio' && !%checked;
2352667Sps156622
23530Sstevel@tonic-gate    $name=$self->escapeHTML($name);
23540Sstevel@tonic-gate
2355667Sps156622    my %tabs = ();
2356*6287Sps156622    if ($TABINDEX && $tabindex) {
2357667Sps156622      if (!ref $tabindex) {
2358667Sps156622          $self->element_tab($tabindex);
2359667Sps156622      } elsif (ref $tabindex eq 'ARRAY') {
2360667Sps156622          %tabs = map {$_=>$self->element_tab} @$tabindex;
2361667Sps156622      } elsif (ref $tabindex eq 'HASH') {
2362667Sps156622          %tabs = %$tabindex;
2363667Sps156622      }
2364667Sps156622    }
2365667Sps156622    %tabs = map {$_=>$self->element_tab} @values unless %tabs;
2366*6287Sps156622    my $other = @other ? "@other " : '';
2367667Sps156622    my $radio_checked;
2368*6287Sps156622
2369*6287Sps156622    # for disabling groups of radio/checkbox buttons
2370*6287Sps156622    my %disabled;
2371*6287Sps156622    foreach (@{$disabled}) {
2372*6287Sps156622   	$disabled{$_}=1;
2373*6287Sps156622    }
2374*6287Sps156622
23750Sstevel@tonic-gate    foreach (@values) {
2376*6287Sps156622    	 my $disable="";
2377*6287Sps156622	 if ($disabled{$_}) {
2378*6287Sps156622		$disable="disabled='1'";
2379*6287Sps156622	 }
2380*6287Sps156622
2381667Sps156622        my $checkit = $self->_checked($box_type eq 'radio' ? ($checked{$_} && !$radio_checked++)
2382667Sps156622                                                           : $checked{$_});
23830Sstevel@tonic-gate	my($break);
23840Sstevel@tonic-gate	if ($linebreak) {
23850Sstevel@tonic-gate          $break = $XHTML ? "<br />" : "<br>";
23860Sstevel@tonic-gate	}
23870Sstevel@tonic-gate	else {
23880Sstevel@tonic-gate	  $break = '';
23890Sstevel@tonic-gate	}
23900Sstevel@tonic-gate	my($label)='';
23910Sstevel@tonic-gate	unless (defined($nolabels) && $nolabels) {
23920Sstevel@tonic-gate	    $label = $_;
23930Sstevel@tonic-gate	    $label = $labels->{$_} if defined($labels) && defined($labels->{$_});
23940Sstevel@tonic-gate	    $label = $self->escapeHTML($label,1);
2395*6287Sps156622            $label = "<span style=\"color:gray\">$label</span>" if $disabled{$_};
23960Sstevel@tonic-gate	}
2397667Sps156622        my $attribs = $self->_set_attributes($_, $attributes);
2398*6287Sps156622        my $tab     = $tabs{$_};
23990Sstevel@tonic-gate	$_=$self->escapeHTML($_);
2400*6287Sps156622
2401667Sps156622        if ($XHTML) {
2402667Sps156622           push @elements,
2403*6287Sps156622              CGI::label($labelattributes,
2404*6287Sps156622                   qq(<input type="$box_type" name="$name" value="$_" $checkit$other$tab$attribs$disable/>$label)).${break};
2405667Sps156622        } else {
2406*6287Sps156622            push(@elements,qq/<input type="$box_type" name="$name" value="$_"$checkit$other$tab$attribs$disable>${label}${break}/);
2407667Sps156622        }
24080Sstevel@tonic-gate    }
24090Sstevel@tonic-gate    $self->register_parameter($name);
2410667Sps156622    return wantarray ? @elements : "@elements"
24110Sstevel@tonic-gate           unless defined($columns) || defined($rows);
24120Sstevel@tonic-gate    return _tableize($rows,$columns,$rowheaders,$colheaders,@elements);
24130Sstevel@tonic-gate}
24140Sstevel@tonic-gateEND_OF_FUNC
24150Sstevel@tonic-gate
24160Sstevel@tonic-gate
24170Sstevel@tonic-gate#### Method: popup_menu
24180Sstevel@tonic-gate# Create a popup menu.
24190Sstevel@tonic-gate# Parameters:
24200Sstevel@tonic-gate#   $name -> Name for all the menu
24210Sstevel@tonic-gate#   $values -> A pointer to a regular array containing the
24220Sstevel@tonic-gate#             text of each menu item.
24230Sstevel@tonic-gate#   $default -> (optional) Default item to display
24240Sstevel@tonic-gate#   $labels -> (optional)
24250Sstevel@tonic-gate#             A pointer to an associative array of labels to print next to each checkbox
24260Sstevel@tonic-gate#             in the form $label{'value'}="Long explanatory label".
24270Sstevel@tonic-gate#             Otherwise the provided values are used as the labels.
24280Sstevel@tonic-gate# Returns:
24290Sstevel@tonic-gate#   A string containing the definition of a popup menu.
24300Sstevel@tonic-gate####
24310Sstevel@tonic-gate'popup_menu' => <<'END_OF_FUNC',
24320Sstevel@tonic-gatesub popup_menu {
24330Sstevel@tonic-gate    my($self,@p) = self_or_default(@_);
24340Sstevel@tonic-gate
2435667Sps156622    my($name,$values,$default,$labels,$attributes,$override,$tabindex,@other) =
24360Sstevel@tonic-gate       rearrange([NAME,[VALUES,VALUE],[DEFAULT,DEFAULTS],LABELS,
2437667Sps156622       ATTRIBUTES,[OVERRIDE,FORCE],TABINDEX],@p);
24380Sstevel@tonic-gate    my($result,$selected);
24390Sstevel@tonic-gate
24400Sstevel@tonic-gate    if (!$override && defined($self->param($name))) {
24410Sstevel@tonic-gate	$selected = $self->param($name);
24420Sstevel@tonic-gate    } else {
24430Sstevel@tonic-gate	$selected = $default;
24440Sstevel@tonic-gate    }
24450Sstevel@tonic-gate    $name=$self->escapeHTML($name);
24460Sstevel@tonic-gate    my($other) = @other ? " @other" : '';
24470Sstevel@tonic-gate
24480Sstevel@tonic-gate    my(@values);
24490Sstevel@tonic-gate    @values = $self->_set_values_and_labels($values,\$labels,$name);
2450667Sps156622    $tabindex = $self->element_tab($tabindex);
2451*6287Sps156622    $result = qq/<select name="$name" $tabindex$other>\n/;
24520Sstevel@tonic-gate    foreach (@values) {
24530Sstevel@tonic-gate        if (/<optgroup/) {
24540Sstevel@tonic-gate            foreach (split(/\n/)) {
24550Sstevel@tonic-gate                my $selectit = $XHTML ? 'selected="selected"' : 'selected';
24560Sstevel@tonic-gate                s/(value="$selected")/$selectit $1/ if defined $selected;
24570Sstevel@tonic-gate                $result .= "$_\n";
24580Sstevel@tonic-gate            }
24590Sstevel@tonic-gate        }
24600Sstevel@tonic-gate        else {
2461*6287Sps156622          my $attribs = $self->_set_attributes($_, $attributes);
2462*6287Sps156622	  my($selectit) = defined($selected) ? $self->_selected($selected eq $_) : '';
2463*6287Sps156622	  my($label) = $_;
2464*6287Sps156622	  $label = $labels->{$_} if defined($labels) && defined($labels->{$_});
2465*6287Sps156622	  my($value) = $self->escapeHTML($_);
2466*6287Sps156622	  $label=$self->escapeHTML($label,1);
2467*6287Sps156622          $result .= "<option${attribs} ${selectit}value=\"$value\">$label</option>\n";
24680Sstevel@tonic-gate        }
24690Sstevel@tonic-gate    }
24700Sstevel@tonic-gate
24710Sstevel@tonic-gate    $result .= "</select>";
24720Sstevel@tonic-gate    return $result;
24730Sstevel@tonic-gate}
24740Sstevel@tonic-gateEND_OF_FUNC
24750Sstevel@tonic-gate
24760Sstevel@tonic-gate
24770Sstevel@tonic-gate#### Method: optgroup
24780Sstevel@tonic-gate# Create a optgroup.
24790Sstevel@tonic-gate# Parameters:
24800Sstevel@tonic-gate#   $name -> Label for the group
24810Sstevel@tonic-gate#   $values -> A pointer to a regular array containing the
24820Sstevel@tonic-gate#              values for each option line in the group.
24830Sstevel@tonic-gate#   $labels -> (optional)
24840Sstevel@tonic-gate#              A pointer to an associative array of labels to print next to each item
24850Sstevel@tonic-gate#              in the form $label{'value'}="Long explanatory label".
24860Sstevel@tonic-gate#              Otherwise the provided values are used as the labels.
24870Sstevel@tonic-gate#   $labeled -> (optional)
24880Sstevel@tonic-gate#               A true value indicates the value should be used as the label attribute
24890Sstevel@tonic-gate#               in the option elements.
24900Sstevel@tonic-gate#               The label attribute specifies the option label presented to the user.
24910Sstevel@tonic-gate#               This defaults to the content of the <option> element, but the label
24920Sstevel@tonic-gate#               attribute allows authors to more easily use optgroup without sacrificing
24930Sstevel@tonic-gate#               compatibility with browsers that do not support option groups.
24940Sstevel@tonic-gate#   $novals -> (optional)
24950Sstevel@tonic-gate#              A true value indicates to suppress the val attribute in the option elements
24960Sstevel@tonic-gate# Returns:
24970Sstevel@tonic-gate#   A string containing the definition of an option group.
24980Sstevel@tonic-gate####
24990Sstevel@tonic-gate'optgroup' => <<'END_OF_FUNC',
25000Sstevel@tonic-gatesub optgroup {
25010Sstevel@tonic-gate    my($self,@p) = self_or_default(@_);
25020Sstevel@tonic-gate    my($name,$values,$attributes,$labeled,$noval,$labels,@other)
25030Sstevel@tonic-gate        = rearrange([NAME,[VALUES,VALUE],ATTRIBUTES,LABELED,NOVALS,LABELS],@p);
25040Sstevel@tonic-gate
25050Sstevel@tonic-gate    my($result,@values);
25060Sstevel@tonic-gate    @values = $self->_set_values_and_labels($values,\$labels,$name,$labeled,$novals);
25070Sstevel@tonic-gate    my($other) = @other ? " @other" : '';
25080Sstevel@tonic-gate
25090Sstevel@tonic-gate    $name=$self->escapeHTML($name);
25100Sstevel@tonic-gate    $result = qq/<optgroup label="$name"$other>\n/;
25110Sstevel@tonic-gate    foreach (@values) {
25120Sstevel@tonic-gate        if (/<optgroup/) {
25130Sstevel@tonic-gate            foreach (split(/\n/)) {
25140Sstevel@tonic-gate                my $selectit = $XHTML ? 'selected="selected"' : 'selected';
25150Sstevel@tonic-gate                s/(value="$selected")/$selectit $1/ if defined $selected;
25160Sstevel@tonic-gate                $result .= "$_\n";
25170Sstevel@tonic-gate            }
25180Sstevel@tonic-gate        }
25190Sstevel@tonic-gate        else {
25200Sstevel@tonic-gate            my $attribs = $self->_set_attributes($_, $attributes);
25210Sstevel@tonic-gate            my($label) = $_;
25220Sstevel@tonic-gate            $label = $labels->{$_} if defined($labels) && defined($labels->{$_});
25230Sstevel@tonic-gate            $label=$self->escapeHTML($label);
25240Sstevel@tonic-gate            my($value)=$self->escapeHTML($_,1);
25250Sstevel@tonic-gate            $result .= $labeled ? $novals ? "<option$attribs label=\"$value\">$label</option>\n"
25260Sstevel@tonic-gate                                          : "<option$attribs label=\"$value\" value=\"$value\">$label</option>\n"
25270Sstevel@tonic-gate                                : $novals ? "<option$attribs>$label</option>\n"
25280Sstevel@tonic-gate                                          : "<option$attribs value=\"$value\">$label</option>\n";
25290Sstevel@tonic-gate        }
25300Sstevel@tonic-gate    }
25310Sstevel@tonic-gate    $result .= "</optgroup>";
25320Sstevel@tonic-gate    return $result;
25330Sstevel@tonic-gate}
25340Sstevel@tonic-gateEND_OF_FUNC
25350Sstevel@tonic-gate
25360Sstevel@tonic-gate
25370Sstevel@tonic-gate#### Method: scrolling_list
25380Sstevel@tonic-gate# Create a scrolling list.
25390Sstevel@tonic-gate# Parameters:
25400Sstevel@tonic-gate#   $name -> name for the list
25410Sstevel@tonic-gate#   $values -> A pointer to a regular array containing the
25420Sstevel@tonic-gate#             values for each option line in the list.
25430Sstevel@tonic-gate#   $defaults -> (optional)
25440Sstevel@tonic-gate#             1. If a pointer to a regular array of options,
25450Sstevel@tonic-gate#             then this will be used to decide which
25460Sstevel@tonic-gate#             lines to turn on by default.
25470Sstevel@tonic-gate#             2. Otherwise holds the value of the single line to turn on.
25480Sstevel@tonic-gate#   $size -> (optional) Size of the list.
25490Sstevel@tonic-gate#   $multiple -> (optional) If set, allow multiple selections.
25500Sstevel@tonic-gate#   $labels -> (optional)
25510Sstevel@tonic-gate#             A pointer to an associative array of labels to print next to each checkbox
25520Sstevel@tonic-gate#             in the form $label{'value'}="Long explanatory label".
25530Sstevel@tonic-gate#             Otherwise the provided values are used as the labels.
25540Sstevel@tonic-gate# Returns:
25550Sstevel@tonic-gate#   A string containing the definition of a scrolling list.
25560Sstevel@tonic-gate####
25570Sstevel@tonic-gate'scrolling_list' => <<'END_OF_FUNC',
25580Sstevel@tonic-gatesub scrolling_list {
25590Sstevel@tonic-gate    my($self,@p) = self_or_default(@_);
2560667Sps156622    my($name,$values,$defaults,$size,$multiple,$labels,$attributes,$override,$tabindex,@other)
25610Sstevel@tonic-gate	= rearrange([NAME,[VALUES,VALUE],[DEFAULTS,DEFAULT],
2562667Sps156622          SIZE,MULTIPLE,LABELS,ATTRIBUTES,[OVERRIDE,FORCE],TABINDEX],@p);
25630Sstevel@tonic-gate
25640Sstevel@tonic-gate    my($result,@values);
25650Sstevel@tonic-gate    @values = $self->_set_values_and_labels($values,\$labels,$name);
25660Sstevel@tonic-gate
25670Sstevel@tonic-gate    $size = $size || scalar(@values);
25680Sstevel@tonic-gate
25690Sstevel@tonic-gate    my(%selected) = $self->previous_or_default($name,$defaults,$override);
25700Sstevel@tonic-gate    my($is_multiple) = $multiple ? qq/ multiple="multiple"/ : '';
25710Sstevel@tonic-gate    my($has_size) = $size ? qq/ size="$size"/: '';
25720Sstevel@tonic-gate    my($other) = @other ? " @other" : '';
25730Sstevel@tonic-gate
25740Sstevel@tonic-gate    $name=$self->escapeHTML($name);
2575667Sps156622    $tabindex = $self->element_tab($tabindex);
2576*6287Sps156622    $result = qq/<select name="$name" $tabindex$has_size$is_multiple$other>\n/;
25770Sstevel@tonic-gate    foreach (@values) {
25780Sstevel@tonic-gate	my($selectit) = $self->_selected($selected{$_});
25790Sstevel@tonic-gate	my($label) = $_;
25800Sstevel@tonic-gate	$label = $labels->{$_} if defined($labels) && defined($labels->{$_});
25810Sstevel@tonic-gate	$label=$self->escapeHTML($label);
25820Sstevel@tonic-gate	my($value)=$self->escapeHTML($_,1);
25830Sstevel@tonic-gate        my $attribs = $self->_set_attributes($_, $attributes);
2584*6287Sps156622        $result .= "<option ${selectit}${attribs}value=\"$value\">$label</option>\n";
25850Sstevel@tonic-gate    }
25860Sstevel@tonic-gate    $result .= "</select>";
25870Sstevel@tonic-gate    $self->register_parameter($name);
25880Sstevel@tonic-gate    return $result;
25890Sstevel@tonic-gate}
25900Sstevel@tonic-gateEND_OF_FUNC
25910Sstevel@tonic-gate
25920Sstevel@tonic-gate
25930Sstevel@tonic-gate#### Method: hidden
25940Sstevel@tonic-gate# Parameters:
25950Sstevel@tonic-gate#   $name -> Name of the hidden field
25960Sstevel@tonic-gate#   @default -> (optional) Initial values of field (may be an array)
25970Sstevel@tonic-gate#      or
25980Sstevel@tonic-gate#   $default->[initial values of field]
25990Sstevel@tonic-gate# Returns:
26000Sstevel@tonic-gate#   A string containing a <input type="hidden" name="name" value="value">
26010Sstevel@tonic-gate####
26020Sstevel@tonic-gate'hidden' => <<'END_OF_FUNC',
26030Sstevel@tonic-gatesub hidden {
26040Sstevel@tonic-gate    my($self,@p) = self_or_default(@_);
26050Sstevel@tonic-gate
26060Sstevel@tonic-gate    # this is the one place where we departed from our standard
26070Sstevel@tonic-gate    # calling scheme, so we have to special-case (darn)
26080Sstevel@tonic-gate    my(@result,@value);
26090Sstevel@tonic-gate    my($name,$default,$override,@other) =
26100Sstevel@tonic-gate	rearrange([NAME,[DEFAULT,VALUE,VALUES],[OVERRIDE,FORCE]],@p);
26110Sstevel@tonic-gate
26120Sstevel@tonic-gate    my $do_override = 0;
26130Sstevel@tonic-gate    if ( ref($p[0]) || substr($p[0],0,1) eq '-') {
26140Sstevel@tonic-gate	@value = ref($default) ? @{$default} : $default;
26150Sstevel@tonic-gate	$do_override = $override;
26160Sstevel@tonic-gate    } else {
26170Sstevel@tonic-gate	foreach ($default,$override,@other) {
26180Sstevel@tonic-gate	    push(@value,$_) if defined($_);
26190Sstevel@tonic-gate	}
26200Sstevel@tonic-gate    }
26210Sstevel@tonic-gate
26220Sstevel@tonic-gate    # use previous values if override is not set
26230Sstevel@tonic-gate    my @prev = $self->param($name);
26240Sstevel@tonic-gate    @value = @prev if !$do_override && @prev;
26250Sstevel@tonic-gate
26260Sstevel@tonic-gate    $name=$self->escapeHTML($name);
26270Sstevel@tonic-gate    foreach (@value) {
26280Sstevel@tonic-gate	$_ = defined($_) ? $self->escapeHTML($_,1) : '';
2629667Sps156622	push @result,$XHTML ? qq(<input type="hidden" name="$name" value="$_" @other />)
2630667Sps156622                            : qq(<input type="hidden" name="$name" value="$_" @other>);
26310Sstevel@tonic-gate    }
26320Sstevel@tonic-gate    return wantarray ? @result : join('',@result);
26330Sstevel@tonic-gate}
26340Sstevel@tonic-gateEND_OF_FUNC
26350Sstevel@tonic-gate
26360Sstevel@tonic-gate
26370Sstevel@tonic-gate#### Method: image_button
26380Sstevel@tonic-gate# Parameters:
26390Sstevel@tonic-gate#   $name -> Name of the button
26400Sstevel@tonic-gate#   $src ->  URL of the image source
26410Sstevel@tonic-gate#   $align -> Alignment style (TOP, BOTTOM or MIDDLE)
26420Sstevel@tonic-gate# Returns:
26430Sstevel@tonic-gate#   A string containing a <input type="image" name="name" src="url" align="alignment">
26440Sstevel@tonic-gate####
26450Sstevel@tonic-gate'image_button' => <<'END_OF_FUNC',
26460Sstevel@tonic-gatesub image_button {
26470Sstevel@tonic-gate    my($self,@p) = self_or_default(@_);
26480Sstevel@tonic-gate
26490Sstevel@tonic-gate    my($name,$src,$alignment,@other) =
26500Sstevel@tonic-gate	rearrange([NAME,SRC,ALIGN],@p);
26510Sstevel@tonic-gate
2652*6287Sps156622    my($align) = $alignment ? " align=\L\"$alignment\"" : '';
26530Sstevel@tonic-gate    my($other) = @other ? " @other" : '';
26540Sstevel@tonic-gate    $name=$self->escapeHTML($name);
26550Sstevel@tonic-gate    return $XHTML ? qq(<input type="image" name="$name" src="$src"$align$other />)
26560Sstevel@tonic-gate                  : qq/<input type="image" name="$name" src="$src"$align$other>/;
26570Sstevel@tonic-gate}
26580Sstevel@tonic-gateEND_OF_FUNC
26590Sstevel@tonic-gate
26600Sstevel@tonic-gate
26610Sstevel@tonic-gate#### Method: self_url
26620Sstevel@tonic-gate# Returns a URL containing the current script and all its
26630Sstevel@tonic-gate# param/value pairs arranged as a query.  You can use this
26640Sstevel@tonic-gate# to create a link that, when selected, will reinvoke the
26650Sstevel@tonic-gate# script with all its state information preserved.
26660Sstevel@tonic-gate####
26670Sstevel@tonic-gate'self_url' => <<'END_OF_FUNC',
26680Sstevel@tonic-gatesub self_url {
26690Sstevel@tonic-gate    my($self,@p) = self_or_default(@_);
26700Sstevel@tonic-gate    return $self->url('-path_info'=>1,'-query'=>1,'-full'=>1,@p);
26710Sstevel@tonic-gate}
26720Sstevel@tonic-gateEND_OF_FUNC
26730Sstevel@tonic-gate
26740Sstevel@tonic-gate
26750Sstevel@tonic-gate# This is provided as a synonym to self_url() for people unfortunate
26760Sstevel@tonic-gate# enough to have incorporated it into their programs already!
26770Sstevel@tonic-gate'state' => <<'END_OF_FUNC',
26780Sstevel@tonic-gatesub state {
26790Sstevel@tonic-gate    &self_url;
26800Sstevel@tonic-gate}
26810Sstevel@tonic-gateEND_OF_FUNC
26820Sstevel@tonic-gate
26830Sstevel@tonic-gate
26840Sstevel@tonic-gate#### Method: url
26850Sstevel@tonic-gate# Like self_url, but doesn't return the query string part of
26860Sstevel@tonic-gate# the URL.
26870Sstevel@tonic-gate####
26880Sstevel@tonic-gate'url' => <<'END_OF_FUNC',
26890Sstevel@tonic-gatesub url {
26900Sstevel@tonic-gate    my($self,@p) = self_or_default(@_);
2691*6287Sps156622    my ($relative,$absolute,$full,$path_info,$query,$base,$rewrite) =
2692*6287Sps156622	rearrange(['RELATIVE','ABSOLUTE','FULL',['PATH','PATH_INFO'],['QUERY','QUERY_STRING'],'BASE','REWRITE'],@p);
2693*6287Sps156622    my $url  = '';
26940Sstevel@tonic-gate    $full++      if $base || !($relative || $absolute);
2695*6287Sps156622    $rewrite++   unless defined $rewrite;
2696*6287Sps156622
2697*6287Sps156622    my $path        =  $self->path_info;
2698*6287Sps156622    my $script_name =  $self->script_name;
2699*6287Sps156622    my $request_uri =  unescape($self->request_uri) || '';
2700*6287Sps156622    my $query_str   =  $self->query_string;
2701*6287Sps156622
2702*6287Sps156622    my $rewrite_in_use = $request_uri && $request_uri !~ /^$script_name/;
2703*6287Sps156622    undef $path if $rewrite_in_use && $rewrite;  # path not valid when rewriting active
2704*6287Sps156622
2705*6287Sps156622    my $uri         =  $rewrite && $request_uri ? $request_uri : $script_name;
2706*6287Sps156622    $uri            =~ s/\?.*$//;                                 # remove query string
2707*6287Sps156622    $uri            =~ s/\Q$path\E$//      if defined $path;      # remove path
27080Sstevel@tonic-gate
27090Sstevel@tonic-gate    if ($full) {
27100Sstevel@tonic-gate	my $protocol = $self->protocol();
27110Sstevel@tonic-gate	$url = "$protocol://";
2712*6287Sps156622	my $vh = http('x_forwarded_host') || http('host') || '';
2713*6287Sps156622        $vh =~ s/\:\d+$//;  # some clients add the port number (incorrectly). Get rid of it.
27140Sstevel@tonic-gate	if ($vh) {
27150Sstevel@tonic-gate	    $url .= $vh;
27160Sstevel@tonic-gate	} else {
27170Sstevel@tonic-gate	    $url .= server_name();
27180Sstevel@tonic-gate	}
2719*6287Sps156622        my $port = $self->server_port;
2720*6287Sps156622	$url .= ":" . $port
2721*6287Sps156622	  unless (lc($protocol) eq 'http'  && $port == 80)
2722*6287Sps156622		|| (lc($protocol) eq 'https' && $port == 443);
27230Sstevel@tonic-gate        return $url if $base;
2724*6287Sps156622	$url .= $uri;
27250Sstevel@tonic-gate    } elsif ($relative) {
2726*6287Sps156622	($url) = $uri =~ m!([^/]+)$!;
27270Sstevel@tonic-gate    } elsif ($absolute) {
2728*6287Sps156622	$url = $uri;
27290Sstevel@tonic-gate    }
27300Sstevel@tonic-gate
2731*6287Sps156622    $url .= $path         if $path_info and defined $path;
2732*6287Sps156622    $url .= "?$query_str" if $query     and $query_str ne '';
2733*6287Sps156622    $url ||= '';
27340Sstevel@tonic-gate    $url =~ s/([^a-zA-Z0-9_.%;&?\/\\:+=~-])/sprintf("%%%02X",ord($1))/eg;
27350Sstevel@tonic-gate    return $url;
27360Sstevel@tonic-gate}
27370Sstevel@tonic-gate
27380Sstevel@tonic-gateEND_OF_FUNC
27390Sstevel@tonic-gate
27400Sstevel@tonic-gate#### Method: cookie
27410Sstevel@tonic-gate# Set or read a cookie from the specified name.
27420Sstevel@tonic-gate# Cookie can then be passed to header().
27430Sstevel@tonic-gate# Usual rules apply to the stickiness of -value.
27440Sstevel@tonic-gate#  Parameters:
27450Sstevel@tonic-gate#   -name -> name for this cookie (optional)
27460Sstevel@tonic-gate#   -value -> value of this cookie (scalar, array or hash)
27470Sstevel@tonic-gate#   -path -> paths for which this cookie is valid (optional)
27480Sstevel@tonic-gate#   -domain -> internet domain in which this cookie is valid (optional)
27490Sstevel@tonic-gate#   -secure -> if true, cookie only passed through secure channel (optional)
27500Sstevel@tonic-gate#   -expires -> expiry date in format Wdy, DD-Mon-YYYY HH:MM:SS GMT (optional)
27510Sstevel@tonic-gate####
27520Sstevel@tonic-gate'cookie' => <<'END_OF_FUNC',
27530Sstevel@tonic-gatesub cookie {
27540Sstevel@tonic-gate    my($self,@p) = self_or_default(@_);
2755*6287Sps156622    my($name,$value,$path,$domain,$secure,$expires,$httponly) =
2756*6287Sps156622	rearrange([NAME,[VALUE,VALUES],PATH,DOMAIN,SECURE,EXPIRES,HTTPONLY],@p);
27570Sstevel@tonic-gate
27580Sstevel@tonic-gate    require CGI::Cookie;
27590Sstevel@tonic-gate
27600Sstevel@tonic-gate    # if no value is supplied, then we retrieve the
27610Sstevel@tonic-gate    # value of the cookie, if any.  For efficiency, we cache the parsed
27620Sstevel@tonic-gate    # cookies in our state variables.
27630Sstevel@tonic-gate    unless ( defined($value) ) {
27640Sstevel@tonic-gate	$self->{'.cookies'} = CGI::Cookie->fetch
27650Sstevel@tonic-gate	    unless $self->{'.cookies'};
27660Sstevel@tonic-gate
27670Sstevel@tonic-gate	# If no name is supplied, then retrieve the names of all our cookies.
27680Sstevel@tonic-gate	return () unless $self->{'.cookies'};
27690Sstevel@tonic-gate	return keys %{$self->{'.cookies'}} unless $name;
27700Sstevel@tonic-gate	return () unless $self->{'.cookies'}->{$name};
27710Sstevel@tonic-gate	return $self->{'.cookies'}->{$name}->value if defined($name) && $name ne '';
27720Sstevel@tonic-gate    }
27730Sstevel@tonic-gate
27740Sstevel@tonic-gate    # If we get here, we're creating a new cookie
27750Sstevel@tonic-gate    return undef unless defined($name) && $name ne '';	# this is an error
27760Sstevel@tonic-gate
27770Sstevel@tonic-gate    my @param;
27780Sstevel@tonic-gate    push(@param,'-name'=>$name);
27790Sstevel@tonic-gate    push(@param,'-value'=>$value);
27800Sstevel@tonic-gate    push(@param,'-domain'=>$domain) if $domain;
27810Sstevel@tonic-gate    push(@param,'-path'=>$path) if $path;
27820Sstevel@tonic-gate    push(@param,'-expires'=>$expires) if $expires;
27830Sstevel@tonic-gate    push(@param,'-secure'=>$secure) if $secure;
2784*6287Sps156622    push(@param,'-httponly'=>$httponly) if $httponly;
27850Sstevel@tonic-gate
27860Sstevel@tonic-gate    return new CGI::Cookie(@param);
27870Sstevel@tonic-gate}
27880Sstevel@tonic-gateEND_OF_FUNC
27890Sstevel@tonic-gate
27900Sstevel@tonic-gate'parse_keywordlist' => <<'END_OF_FUNC',
27910Sstevel@tonic-gatesub parse_keywordlist {
27920Sstevel@tonic-gate    my($self,$tosplit) = @_;
27930Sstevel@tonic-gate    $tosplit = unescape($tosplit); # unescape the keywords
27940Sstevel@tonic-gate    $tosplit=~tr/+/ /;          # pluses to spaces
27950Sstevel@tonic-gate    my(@keywords) = split(/\s+/,$tosplit);
27960Sstevel@tonic-gate    return @keywords;
27970Sstevel@tonic-gate}
27980Sstevel@tonic-gateEND_OF_FUNC
27990Sstevel@tonic-gate
28000Sstevel@tonic-gate'param_fetch' => <<'END_OF_FUNC',
28010Sstevel@tonic-gatesub param_fetch {
28020Sstevel@tonic-gate    my($self,@p) = self_or_default(@_);
28030Sstevel@tonic-gate    my($name) = rearrange([NAME],@p);
28040Sstevel@tonic-gate    unless (exists($self->{$name})) {
28050Sstevel@tonic-gate	$self->add_parameter($name);
28060Sstevel@tonic-gate	$self->{$name} = [];
28070Sstevel@tonic-gate    }
28080Sstevel@tonic-gate
28090Sstevel@tonic-gate    return $self->{$name};
28100Sstevel@tonic-gate}
28110Sstevel@tonic-gateEND_OF_FUNC
28120Sstevel@tonic-gate
28130Sstevel@tonic-gate###############################################
28140Sstevel@tonic-gate# OTHER INFORMATION PROVIDED BY THE ENVIRONMENT
28150Sstevel@tonic-gate###############################################
28160Sstevel@tonic-gate
28170Sstevel@tonic-gate#### Method: path_info
28180Sstevel@tonic-gate# Return the extra virtual path information provided
28190Sstevel@tonic-gate# after the URL (if any)
28200Sstevel@tonic-gate####
28210Sstevel@tonic-gate'path_info' => <<'END_OF_FUNC',
28220Sstevel@tonic-gatesub path_info {
28230Sstevel@tonic-gate    my ($self,$info) = self_or_default(@_);
28240Sstevel@tonic-gate    if (defined($info)) {
28250Sstevel@tonic-gate	$info = "/$info" if $info ne '' &&  substr($info,0,1) ne '/';
28260Sstevel@tonic-gate	$self->{'.path_info'} = $info;
28270Sstevel@tonic-gate    } elsif (! defined($self->{'.path_info'}) ) {
2828667Sps156622        my (undef,$path_info) = $self->_name_and_path_from_env;
2829667Sps156622	$self->{'.path_info'} = $path_info || '';
28300Sstevel@tonic-gate    }
28310Sstevel@tonic-gate    return $self->{'.path_info'};
28320Sstevel@tonic-gate}
28330Sstevel@tonic-gateEND_OF_FUNC
28340Sstevel@tonic-gate
2835667Sps156622# WE USE THIS TO COMPENSATE FOR A BUG IN APACHE 2 PRESENT AT LEAST UP THROUGH 2.0.54
2836667Sps156622'_name_and_path_from_env' => <<'END_OF_FUNC',
2837667Sps156622sub _name_and_path_from_env {
2838667Sps156622   my $self = shift;
2839667Sps156622   my $raw_script_name = $ENV{SCRIPT_NAME} || '';
2840667Sps156622   my $raw_path_info   = $ENV{PATH_INFO}   || '';
2841*6287Sps156622   my $uri             = unescape($self->request_uri) || '';
2842*6287Sps156622
2843*6287Sps156622   my $protected    = quotemeta($raw_path_info);
2844*6287Sps156622   $raw_script_name =~ s/$protected$//;
2845667Sps156622
2846667Sps156622   my @uri_double_slashes  = $uri =~ m^(/{2,}?)^g;
2847667Sps156622   my @path_double_slashes = "$raw_script_name $raw_path_info" =~ m^(/{2,}?)^g;
2848667Sps156622
2849667Sps156622   my $apache_bug      = @uri_double_slashes != @path_double_slashes;
2850667Sps156622   return ($raw_script_name,$raw_path_info) unless $apache_bug;
2851667Sps156622
2852*6287Sps156622   my $path_info_search = quotemeta($raw_path_info);
2853667Sps156622   $path_info_search    =~ s!/!/+!g;
2854667Sps156622   if ($uri =~ m/^(.+)($path_info_search)/) {
2855667Sps156622       return ($1,$2);
2856667Sps156622   } else {
2857667Sps156622       return ($raw_script_name,$raw_path_info);
2858667Sps156622   }
2859667Sps156622}
2860667Sps156622END_OF_FUNC
2861667Sps156622
28620Sstevel@tonic-gate
28630Sstevel@tonic-gate#### Method: request_method
28640Sstevel@tonic-gate# Returns 'POST', 'GET', 'PUT' or 'HEAD'
28650Sstevel@tonic-gate####
28660Sstevel@tonic-gate'request_method' => <<'END_OF_FUNC',
28670Sstevel@tonic-gatesub request_method {
28680Sstevel@tonic-gate    return $ENV{'REQUEST_METHOD'};
28690Sstevel@tonic-gate}
28700Sstevel@tonic-gateEND_OF_FUNC
28710Sstevel@tonic-gate
28720Sstevel@tonic-gate#### Method: content_type
28730Sstevel@tonic-gate# Returns the content_type string
28740Sstevel@tonic-gate####
28750Sstevel@tonic-gate'content_type' => <<'END_OF_FUNC',
28760Sstevel@tonic-gatesub content_type {
28770Sstevel@tonic-gate    return $ENV{'CONTENT_TYPE'};
28780Sstevel@tonic-gate}
28790Sstevel@tonic-gateEND_OF_FUNC
28800Sstevel@tonic-gate
28810Sstevel@tonic-gate#### Method: path_translated
28820Sstevel@tonic-gate# Return the physical path information provided
28830Sstevel@tonic-gate# by the URL (if any)
28840Sstevel@tonic-gate####
28850Sstevel@tonic-gate'path_translated' => <<'END_OF_FUNC',
28860Sstevel@tonic-gatesub path_translated {
28870Sstevel@tonic-gate    return $ENV{'PATH_TRANSLATED'};
28880Sstevel@tonic-gate}
28890Sstevel@tonic-gateEND_OF_FUNC
28900Sstevel@tonic-gate
28910Sstevel@tonic-gate
2892667Sps156622#### Method: request_uri
2893667Sps156622# Return the literal request URI
2894667Sps156622####
2895667Sps156622'request_uri' => <<'END_OF_FUNC',
2896667Sps156622sub request_uri {
2897667Sps156622    return $ENV{'REQUEST_URI'};
2898667Sps156622}
2899667Sps156622END_OF_FUNC
2900667Sps156622
2901667Sps156622
29020Sstevel@tonic-gate#### Method: query_string
29030Sstevel@tonic-gate# Synthesize a query string from our current
29040Sstevel@tonic-gate# parameters
29050Sstevel@tonic-gate####
29060Sstevel@tonic-gate'query_string' => <<'END_OF_FUNC',
29070Sstevel@tonic-gatesub query_string {
29080Sstevel@tonic-gate    my($self) = self_or_default(@_);
29090Sstevel@tonic-gate    my($param,$value,@pairs);
29100Sstevel@tonic-gate    foreach $param ($self->param) {
29110Sstevel@tonic-gate	my($eparam) = escape($param);
29120Sstevel@tonic-gate	foreach $value ($self->param($param)) {
29130Sstevel@tonic-gate	    $value = escape($value);
29140Sstevel@tonic-gate            next unless defined $value;
29150Sstevel@tonic-gate	    push(@pairs,"$eparam=$value");
29160Sstevel@tonic-gate	}
29170Sstevel@tonic-gate    }
29180Sstevel@tonic-gate    foreach (keys %{$self->{'.fieldnames'}}) {
29190Sstevel@tonic-gate      push(@pairs,".cgifields=".escape("$_"));
29200Sstevel@tonic-gate    }
29210Sstevel@tonic-gate    return join($USE_PARAM_SEMICOLONS ? ';' : '&',@pairs);
29220Sstevel@tonic-gate}
29230Sstevel@tonic-gateEND_OF_FUNC
29240Sstevel@tonic-gate
29250Sstevel@tonic-gate
29260Sstevel@tonic-gate#### Method: accept
29270Sstevel@tonic-gate# Without parameters, returns an array of the
29280Sstevel@tonic-gate# MIME types the browser accepts.
29290Sstevel@tonic-gate# With a single parameter equal to a MIME
29300Sstevel@tonic-gate# type, will return undef if the browser won't
29310Sstevel@tonic-gate# accept it, 1 if the browser accepts it but
29320Sstevel@tonic-gate# doesn't give a preference, or a floating point
29330Sstevel@tonic-gate# value between 0.0 and 1.0 if the browser
29340Sstevel@tonic-gate# declares a quantitative score for it.
29350Sstevel@tonic-gate# This handles MIME type globs correctly.
29360Sstevel@tonic-gate####
29370Sstevel@tonic-gate'Accept' => <<'END_OF_FUNC',
29380Sstevel@tonic-gatesub Accept {
29390Sstevel@tonic-gate    my($self,$search) = self_or_CGI(@_);
29400Sstevel@tonic-gate    my(%prefs,$type,$pref,$pat);
29410Sstevel@tonic-gate
29420Sstevel@tonic-gate    my(@accept) = split(',',$self->http('accept'));
29430Sstevel@tonic-gate
29440Sstevel@tonic-gate    foreach (@accept) {
29450Sstevel@tonic-gate	($pref) = /q=(\d\.\d+|\d+)/;
29460Sstevel@tonic-gate	($type) = m#(\S+/[^;]+)#;
29470Sstevel@tonic-gate	next unless $type;
29480Sstevel@tonic-gate	$prefs{$type}=$pref || 1;
29490Sstevel@tonic-gate    }
29500Sstevel@tonic-gate
29510Sstevel@tonic-gate    return keys %prefs unless $search;
29520Sstevel@tonic-gate
29530Sstevel@tonic-gate    # if a search type is provided, we may need to
29540Sstevel@tonic-gate    # perform a pattern matching operation.
29550Sstevel@tonic-gate    # The MIME types use a glob mechanism, which
29560Sstevel@tonic-gate    # is easily translated into a perl pattern match
29570Sstevel@tonic-gate
29580Sstevel@tonic-gate    # First return the preference for directly supported
29590Sstevel@tonic-gate    # types:
29600Sstevel@tonic-gate    return $prefs{$search} if $prefs{$search};
29610Sstevel@tonic-gate
29620Sstevel@tonic-gate    # Didn't get it, so try pattern matching.
29630Sstevel@tonic-gate    foreach (keys %prefs) {
29640Sstevel@tonic-gate	next unless /\*/;       # not a pattern match
29650Sstevel@tonic-gate	($pat = $_) =~ s/([^\w*])/\\$1/g; # escape meta characters
29660Sstevel@tonic-gate	$pat =~ s/\*/.*/g; # turn it into a pattern
29670Sstevel@tonic-gate	return $prefs{$_} if $search=~/$pat/;
29680Sstevel@tonic-gate    }
29690Sstevel@tonic-gate}
29700Sstevel@tonic-gateEND_OF_FUNC
29710Sstevel@tonic-gate
29720Sstevel@tonic-gate
29730Sstevel@tonic-gate#### Method: user_agent
29740Sstevel@tonic-gate# If called with no parameters, returns the user agent.
29750Sstevel@tonic-gate# If called with one parameter, does a pattern match (case
29760Sstevel@tonic-gate# insensitive) on the user agent.
29770Sstevel@tonic-gate####
29780Sstevel@tonic-gate'user_agent' => <<'END_OF_FUNC',
29790Sstevel@tonic-gatesub user_agent {
29800Sstevel@tonic-gate    my($self,$match)=self_or_CGI(@_);
29810Sstevel@tonic-gate    return $self->http('user_agent') unless $match;
29820Sstevel@tonic-gate    return $self->http('user_agent') =~ /$match/i;
29830Sstevel@tonic-gate}
29840Sstevel@tonic-gateEND_OF_FUNC
29850Sstevel@tonic-gate
29860Sstevel@tonic-gate
29870Sstevel@tonic-gate#### Method: raw_cookie
29880Sstevel@tonic-gate# Returns the magic cookies for the session.
29890Sstevel@tonic-gate# The cookies are not parsed or altered in any way, i.e.
29900Sstevel@tonic-gate# cookies are returned exactly as given in the HTTP
29910Sstevel@tonic-gate# headers.  If a cookie name is given, only that cookie's
29920Sstevel@tonic-gate# value is returned, otherwise the entire raw cookie
29930Sstevel@tonic-gate# is returned.
29940Sstevel@tonic-gate####
29950Sstevel@tonic-gate'raw_cookie' => <<'END_OF_FUNC',
29960Sstevel@tonic-gatesub raw_cookie {
29970Sstevel@tonic-gate    my($self,$key) = self_or_CGI(@_);
29980Sstevel@tonic-gate
29990Sstevel@tonic-gate    require CGI::Cookie;
30000Sstevel@tonic-gate
30010Sstevel@tonic-gate    if (defined($key)) {
30020Sstevel@tonic-gate	$self->{'.raw_cookies'} = CGI::Cookie->raw_fetch
30030Sstevel@tonic-gate	    unless $self->{'.raw_cookies'};
30040Sstevel@tonic-gate
30050Sstevel@tonic-gate	return () unless $self->{'.raw_cookies'};
30060Sstevel@tonic-gate	return () unless $self->{'.raw_cookies'}->{$key};
30070Sstevel@tonic-gate	return $self->{'.raw_cookies'}->{$key};
30080Sstevel@tonic-gate    }
30090Sstevel@tonic-gate    return $self->http('cookie') || $ENV{'COOKIE'} || '';
30100Sstevel@tonic-gate}
30110Sstevel@tonic-gateEND_OF_FUNC
30120Sstevel@tonic-gate
30130Sstevel@tonic-gate#### Method: virtual_host
30140Sstevel@tonic-gate# Return the name of the virtual_host, which
30150Sstevel@tonic-gate# is not always the same as the server
30160Sstevel@tonic-gate######
30170Sstevel@tonic-gate'virtual_host' => <<'END_OF_FUNC',
30180Sstevel@tonic-gatesub virtual_host {
3019667Sps156622    my $vh = http('x_forwarded_host') || http('host') || server_name();
30200Sstevel@tonic-gate    $vh =~ s/:\d+$//;		# get rid of port number
30210Sstevel@tonic-gate    return $vh;
30220Sstevel@tonic-gate}
30230Sstevel@tonic-gateEND_OF_FUNC
30240Sstevel@tonic-gate
30250Sstevel@tonic-gate#### Method: remote_host
30260Sstevel@tonic-gate# Return the name of the remote host, or its IP
30270Sstevel@tonic-gate# address if unavailable.  If this variable isn't
30280Sstevel@tonic-gate# defined, it returns "localhost" for debugging
30290Sstevel@tonic-gate# purposes.
30300Sstevel@tonic-gate####
30310Sstevel@tonic-gate'remote_host' => <<'END_OF_FUNC',
30320Sstevel@tonic-gatesub remote_host {
30330Sstevel@tonic-gate    return $ENV{'REMOTE_HOST'} || $ENV{'REMOTE_ADDR'}
30340Sstevel@tonic-gate    || 'localhost';
30350Sstevel@tonic-gate}
30360Sstevel@tonic-gateEND_OF_FUNC
30370Sstevel@tonic-gate
30380Sstevel@tonic-gate
30390Sstevel@tonic-gate#### Method: remote_addr
30400Sstevel@tonic-gate# Return the IP addr of the remote host.
30410Sstevel@tonic-gate####
30420Sstevel@tonic-gate'remote_addr' => <<'END_OF_FUNC',
30430Sstevel@tonic-gatesub remote_addr {
30440Sstevel@tonic-gate    return $ENV{'REMOTE_ADDR'} || '127.0.0.1';
30450Sstevel@tonic-gate}
30460Sstevel@tonic-gateEND_OF_FUNC
30470Sstevel@tonic-gate
30480Sstevel@tonic-gate
30490Sstevel@tonic-gate#### Method: script_name
30500Sstevel@tonic-gate# Return the partial URL to this script for
30510Sstevel@tonic-gate# self-referencing scripts.  Also see
30520Sstevel@tonic-gate# self_url(), which returns a URL with all state information
30530Sstevel@tonic-gate# preserved.
30540Sstevel@tonic-gate####
30550Sstevel@tonic-gate'script_name' => <<'END_OF_FUNC',
30560Sstevel@tonic-gatesub script_name {
3057667Sps156622    my ($self,@p) = self_or_default(@_);
3058667Sps156622    if (@p) {
3059*6287Sps156622        $self->{'.script_name'} = shift @p;
3060667Sps156622    } elsif (!exists $self->{'.script_name'}) {
3061667Sps156622        my ($script_name,$path_info) = $self->_name_and_path_from_env();
3062667Sps156622        $self->{'.script_name'} = $script_name;
3063667Sps156622    }
3064667Sps156622    return $self->{'.script_name'};
30650Sstevel@tonic-gate}
30660Sstevel@tonic-gateEND_OF_FUNC
30670Sstevel@tonic-gate
30680Sstevel@tonic-gate
30690Sstevel@tonic-gate#### Method: referer
30700Sstevel@tonic-gate# Return the HTTP_REFERER: useful for generating
30710Sstevel@tonic-gate# a GO BACK button.
30720Sstevel@tonic-gate####
30730Sstevel@tonic-gate'referer' => <<'END_OF_FUNC',
30740Sstevel@tonic-gatesub referer {
30750Sstevel@tonic-gate    my($self) = self_or_CGI(@_);
30760Sstevel@tonic-gate    return $self->http('referer');
30770Sstevel@tonic-gate}
30780Sstevel@tonic-gateEND_OF_FUNC
30790Sstevel@tonic-gate
30800Sstevel@tonic-gate
30810Sstevel@tonic-gate#### Method: server_name
30820Sstevel@tonic-gate# Return the name of the server
30830Sstevel@tonic-gate####
30840Sstevel@tonic-gate'server_name' => <<'END_OF_FUNC',
30850Sstevel@tonic-gatesub server_name {
30860Sstevel@tonic-gate    return $ENV{'SERVER_NAME'} || 'localhost';
30870Sstevel@tonic-gate}
30880Sstevel@tonic-gateEND_OF_FUNC
30890Sstevel@tonic-gate
30900Sstevel@tonic-gate#### Method: server_software
30910Sstevel@tonic-gate# Return the name of the server software
30920Sstevel@tonic-gate####
30930Sstevel@tonic-gate'server_software' => <<'END_OF_FUNC',
30940Sstevel@tonic-gatesub server_software {
30950Sstevel@tonic-gate    return $ENV{'SERVER_SOFTWARE'} || 'cmdline';
30960Sstevel@tonic-gate}
30970Sstevel@tonic-gateEND_OF_FUNC
30980Sstevel@tonic-gate
30990Sstevel@tonic-gate#### Method: virtual_port
31000Sstevel@tonic-gate# Return the server port, taking virtual hosts into account
31010Sstevel@tonic-gate####
31020Sstevel@tonic-gate'virtual_port' => <<'END_OF_FUNC',
31030Sstevel@tonic-gatesub virtual_port {
31040Sstevel@tonic-gate    my($self) = self_or_default(@_);
3105667Sps156622    my $vh = $self->http('x_forwarded_host') || $self->http('host');
3106*6287Sps156622    my $protocol = $self->protocol;
31070Sstevel@tonic-gate    if ($vh) {
3108*6287Sps156622        return ($vh =~ /:(\d+)$/)[0] || ($protocol eq 'https' ? 443 : 80);
31090Sstevel@tonic-gate    } else {
31100Sstevel@tonic-gate        return $self->server_port();
31110Sstevel@tonic-gate    }
31120Sstevel@tonic-gate}
31130Sstevel@tonic-gateEND_OF_FUNC
31140Sstevel@tonic-gate
31150Sstevel@tonic-gate#### Method: server_port
31160Sstevel@tonic-gate# Return the tcp/ip port the server is running on
31170Sstevel@tonic-gate####
31180Sstevel@tonic-gate'server_port' => <<'END_OF_FUNC',
31190Sstevel@tonic-gatesub server_port {
31200Sstevel@tonic-gate    return $ENV{'SERVER_PORT'} || 80; # for debugging
31210Sstevel@tonic-gate}
31220Sstevel@tonic-gateEND_OF_FUNC
31230Sstevel@tonic-gate
31240Sstevel@tonic-gate#### Method: server_protocol
31250Sstevel@tonic-gate# Return the protocol (usually HTTP/1.0)
31260Sstevel@tonic-gate####
31270Sstevel@tonic-gate'server_protocol' => <<'END_OF_FUNC',
31280Sstevel@tonic-gatesub server_protocol {
31290Sstevel@tonic-gate    return $ENV{'SERVER_PROTOCOL'} || 'HTTP/1.0'; # for debugging
31300Sstevel@tonic-gate}
31310Sstevel@tonic-gateEND_OF_FUNC
31320Sstevel@tonic-gate
31330Sstevel@tonic-gate#### Method: http
31340Sstevel@tonic-gate# Return the value of an HTTP variable, or
31350Sstevel@tonic-gate# the list of variables if none provided
31360Sstevel@tonic-gate####
31370Sstevel@tonic-gate'http' => <<'END_OF_FUNC',
31380Sstevel@tonic-gatesub http {
31390Sstevel@tonic-gate    my ($self,$parameter) = self_or_CGI(@_);
31400Sstevel@tonic-gate    return $ENV{$parameter} if $parameter=~/^HTTP/;
31410Sstevel@tonic-gate    $parameter =~ tr/-/_/;
31420Sstevel@tonic-gate    return $ENV{"HTTP_\U$parameter\E"} if $parameter;
31430Sstevel@tonic-gate    my(@p);
31440Sstevel@tonic-gate    foreach (keys %ENV) {
31450Sstevel@tonic-gate	push(@p,$_) if /^HTTP/;
31460Sstevel@tonic-gate    }
31470Sstevel@tonic-gate    return @p;
31480Sstevel@tonic-gate}
31490Sstevel@tonic-gateEND_OF_FUNC
31500Sstevel@tonic-gate
31510Sstevel@tonic-gate#### Method: https
31520Sstevel@tonic-gate# Return the value of HTTPS
31530Sstevel@tonic-gate####
31540Sstevel@tonic-gate'https' => <<'END_OF_FUNC',
31550Sstevel@tonic-gatesub https {
31560Sstevel@tonic-gate    local($^W)=0;
31570Sstevel@tonic-gate    my ($self,$parameter) = self_or_CGI(@_);
31580Sstevel@tonic-gate    return $ENV{HTTPS} unless $parameter;
31590Sstevel@tonic-gate    return $ENV{$parameter} if $parameter=~/^HTTPS/;
31600Sstevel@tonic-gate    $parameter =~ tr/-/_/;
31610Sstevel@tonic-gate    return $ENV{"HTTPS_\U$parameter\E"} if $parameter;
31620Sstevel@tonic-gate    my(@p);
31630Sstevel@tonic-gate    foreach (keys %ENV) {
31640Sstevel@tonic-gate	push(@p,$_) if /^HTTPS/;
31650Sstevel@tonic-gate    }
31660Sstevel@tonic-gate    return @p;
31670Sstevel@tonic-gate}
31680Sstevel@tonic-gateEND_OF_FUNC
31690Sstevel@tonic-gate
31700Sstevel@tonic-gate#### Method: protocol
31710Sstevel@tonic-gate# Return the protocol (http or https currently)
31720Sstevel@tonic-gate####
31730Sstevel@tonic-gate'protocol' => <<'END_OF_FUNC',
31740Sstevel@tonic-gatesub protocol {
31750Sstevel@tonic-gate    local($^W)=0;
31760Sstevel@tonic-gate    my $self = shift;
31770Sstevel@tonic-gate    return 'https' if uc($self->https()) eq 'ON';
31780Sstevel@tonic-gate    return 'https' if $self->server_port == 443;
31790Sstevel@tonic-gate    my $prot = $self->server_protocol;
31800Sstevel@tonic-gate    my($protocol,$version) = split('/',$prot);
31810Sstevel@tonic-gate    return "\L$protocol\E";
31820Sstevel@tonic-gate}
31830Sstevel@tonic-gateEND_OF_FUNC
31840Sstevel@tonic-gate
31850Sstevel@tonic-gate#### Method: remote_ident
31860Sstevel@tonic-gate# Return the identity of the remote user
31870Sstevel@tonic-gate# (but only if his host is running identd)
31880Sstevel@tonic-gate####
31890Sstevel@tonic-gate'remote_ident' => <<'END_OF_FUNC',
31900Sstevel@tonic-gatesub remote_ident {
31910Sstevel@tonic-gate    return $ENV{'REMOTE_IDENT'};
31920Sstevel@tonic-gate}
31930Sstevel@tonic-gateEND_OF_FUNC
31940Sstevel@tonic-gate
31950Sstevel@tonic-gate
31960Sstevel@tonic-gate#### Method: auth_type
31970Sstevel@tonic-gate# Return the type of use verification/authorization in use, if any.
31980Sstevel@tonic-gate####
31990Sstevel@tonic-gate'auth_type' => <<'END_OF_FUNC',
32000Sstevel@tonic-gatesub auth_type {
32010Sstevel@tonic-gate    return $ENV{'AUTH_TYPE'};
32020Sstevel@tonic-gate}
32030Sstevel@tonic-gateEND_OF_FUNC
32040Sstevel@tonic-gate
32050Sstevel@tonic-gate
32060Sstevel@tonic-gate#### Method: remote_user
32070Sstevel@tonic-gate# Return the authorization name used for user
32080Sstevel@tonic-gate# verification.
32090Sstevel@tonic-gate####
32100Sstevel@tonic-gate'remote_user' => <<'END_OF_FUNC',
32110Sstevel@tonic-gatesub remote_user {
32120Sstevel@tonic-gate    return $ENV{'REMOTE_USER'};
32130Sstevel@tonic-gate}
32140Sstevel@tonic-gateEND_OF_FUNC
32150Sstevel@tonic-gate
32160Sstevel@tonic-gate
32170Sstevel@tonic-gate#### Method: user_name
32180Sstevel@tonic-gate# Try to return the remote user's name by hook or by
32190Sstevel@tonic-gate# crook
32200Sstevel@tonic-gate####
32210Sstevel@tonic-gate'user_name' => <<'END_OF_FUNC',
32220Sstevel@tonic-gatesub user_name {
32230Sstevel@tonic-gate    my ($self) = self_or_CGI(@_);
32240Sstevel@tonic-gate    return $self->http('from') || $ENV{'REMOTE_IDENT'} || $ENV{'REMOTE_USER'};
32250Sstevel@tonic-gate}
32260Sstevel@tonic-gateEND_OF_FUNC
32270Sstevel@tonic-gate
32280Sstevel@tonic-gate#### Method: nosticky
32290Sstevel@tonic-gate# Set or return the NOSTICKY global flag
32300Sstevel@tonic-gate####
32310Sstevel@tonic-gate'nosticky' => <<'END_OF_FUNC',
32320Sstevel@tonic-gatesub nosticky {
32330Sstevel@tonic-gate    my ($self,$param) = self_or_CGI(@_);
32340Sstevel@tonic-gate    $CGI::NOSTICKY = $param if defined($param);
32350Sstevel@tonic-gate    return $CGI::NOSTICKY;
32360Sstevel@tonic-gate}
32370Sstevel@tonic-gateEND_OF_FUNC
32380Sstevel@tonic-gate
32390Sstevel@tonic-gate#### Method: nph
32400Sstevel@tonic-gate# Set or return the NPH global flag
32410Sstevel@tonic-gate####
32420Sstevel@tonic-gate'nph' => <<'END_OF_FUNC',
32430Sstevel@tonic-gatesub nph {
32440Sstevel@tonic-gate    my ($self,$param) = self_or_CGI(@_);
32450Sstevel@tonic-gate    $CGI::NPH = $param if defined($param);
32460Sstevel@tonic-gate    return $CGI::NPH;
32470Sstevel@tonic-gate}
32480Sstevel@tonic-gateEND_OF_FUNC
32490Sstevel@tonic-gate
32500Sstevel@tonic-gate#### Method: private_tempfiles
32510Sstevel@tonic-gate# Set or return the private_tempfiles global flag
32520Sstevel@tonic-gate####
32530Sstevel@tonic-gate'private_tempfiles' => <<'END_OF_FUNC',
32540Sstevel@tonic-gatesub private_tempfiles {
32550Sstevel@tonic-gate    my ($self,$param) = self_or_CGI(@_);
32560Sstevel@tonic-gate    $CGI::PRIVATE_TEMPFILES = $param if defined($param);
32570Sstevel@tonic-gate    return $CGI::PRIVATE_TEMPFILES;
32580Sstevel@tonic-gate}
32590Sstevel@tonic-gateEND_OF_FUNC
32600Sstevel@tonic-gate#### Method: close_upload_files
32610Sstevel@tonic-gate# Set or return the close_upload_files global flag
32620Sstevel@tonic-gate####
32630Sstevel@tonic-gate'close_upload_files' => <<'END_OF_FUNC',
32640Sstevel@tonic-gatesub close_upload_files {
32650Sstevel@tonic-gate    my ($self,$param) = self_or_CGI(@_);
32660Sstevel@tonic-gate    $CGI::CLOSE_UPLOAD_FILES = $param if defined($param);
32670Sstevel@tonic-gate    return $CGI::CLOSE_UPLOAD_FILES;
32680Sstevel@tonic-gate}
32690Sstevel@tonic-gateEND_OF_FUNC
32700Sstevel@tonic-gate
32710Sstevel@tonic-gate
32720Sstevel@tonic-gate#### Method: default_dtd
32730Sstevel@tonic-gate# Set or return the default_dtd global
32740Sstevel@tonic-gate####
32750Sstevel@tonic-gate'default_dtd' => <<'END_OF_FUNC',
32760Sstevel@tonic-gatesub default_dtd {
32770Sstevel@tonic-gate    my ($self,$param,$param2) = self_or_CGI(@_);
32780Sstevel@tonic-gate    if (defined $param2 && defined $param) {
32790Sstevel@tonic-gate        $CGI::DEFAULT_DTD = [ $param, $param2 ];
32800Sstevel@tonic-gate    } elsif (defined $param) {
32810Sstevel@tonic-gate        $CGI::DEFAULT_DTD = $param;
32820Sstevel@tonic-gate    }
32830Sstevel@tonic-gate    return $CGI::DEFAULT_DTD;
32840Sstevel@tonic-gate}
32850Sstevel@tonic-gateEND_OF_FUNC
32860Sstevel@tonic-gate
32870Sstevel@tonic-gate# -------------- really private subroutines -----------------
32880Sstevel@tonic-gate'previous_or_default' => <<'END_OF_FUNC',
32890Sstevel@tonic-gatesub previous_or_default {
32900Sstevel@tonic-gate    my($self,$name,$defaults,$override) = @_;
32910Sstevel@tonic-gate    my(%selected);
32920Sstevel@tonic-gate
32930Sstevel@tonic-gate    if (!$override && ($self->{'.fieldnames'}->{$name} ||
32940Sstevel@tonic-gate		       defined($self->param($name)) ) ) {
32950Sstevel@tonic-gate	grep($selected{$_}++,$self->param($name));
32960Sstevel@tonic-gate    } elsif (defined($defaults) && ref($defaults) &&
32970Sstevel@tonic-gate	     (ref($defaults) eq 'ARRAY')) {
32980Sstevel@tonic-gate	grep($selected{$_}++,@{$defaults});
32990Sstevel@tonic-gate    } else {
33000Sstevel@tonic-gate	$selected{$defaults}++ if defined($defaults);
33010Sstevel@tonic-gate    }
33020Sstevel@tonic-gate
33030Sstevel@tonic-gate    return %selected;
33040Sstevel@tonic-gate}
33050Sstevel@tonic-gateEND_OF_FUNC
33060Sstevel@tonic-gate
33070Sstevel@tonic-gate'register_parameter' => <<'END_OF_FUNC',
33080Sstevel@tonic-gatesub register_parameter {
33090Sstevel@tonic-gate    my($self,$param) = @_;
33100Sstevel@tonic-gate    $self->{'.parametersToAdd'}->{$param}++;
33110Sstevel@tonic-gate}
33120Sstevel@tonic-gateEND_OF_FUNC
33130Sstevel@tonic-gate
33140Sstevel@tonic-gate'get_fields' => <<'END_OF_FUNC',
33150Sstevel@tonic-gatesub get_fields {
33160Sstevel@tonic-gate    my($self) = @_;
33170Sstevel@tonic-gate    return $self->CGI::hidden('-name'=>'.cgifields',
33180Sstevel@tonic-gate			      '-values'=>[keys %{$self->{'.parametersToAdd'}}],
33190Sstevel@tonic-gate			      '-override'=>1);
33200Sstevel@tonic-gate}
33210Sstevel@tonic-gateEND_OF_FUNC
33220Sstevel@tonic-gate
33230Sstevel@tonic-gate'read_from_cmdline' => <<'END_OF_FUNC',
33240Sstevel@tonic-gatesub read_from_cmdline {
33250Sstevel@tonic-gate    my($input,@words);
33260Sstevel@tonic-gate    my($query_string);
33270Sstevel@tonic-gate    my($subpath);
33280Sstevel@tonic-gate    if ($DEBUG && @ARGV) {
33290Sstevel@tonic-gate	@words = @ARGV;
33300Sstevel@tonic-gate    } elsif ($DEBUG > 1) {
33310Sstevel@tonic-gate	require "shellwords.pl";
33320Sstevel@tonic-gate	print STDERR "(offline mode: enter name=value pairs on standard input; press ^D or ^Z when done)\n";
33330Sstevel@tonic-gate	chomp(@lines = <STDIN>); # remove newlines
33340Sstevel@tonic-gate	$input = join(" ",@lines);
33350Sstevel@tonic-gate	@words = &shellwords($input);
33360Sstevel@tonic-gate    }
33370Sstevel@tonic-gate    foreach (@words) {
33380Sstevel@tonic-gate	s/\\=/%3D/g;
33390Sstevel@tonic-gate	s/\\&/%26/g;
33400Sstevel@tonic-gate    }
33410Sstevel@tonic-gate
33420Sstevel@tonic-gate    if ("@words"=~/=/) {
33430Sstevel@tonic-gate	$query_string = join('&',@words);
33440Sstevel@tonic-gate    } else {
33450Sstevel@tonic-gate	$query_string = join('+',@words);
33460Sstevel@tonic-gate    }
33470Sstevel@tonic-gate    if ($query_string =~ /^(.*?)\?(.*)$/)
33480Sstevel@tonic-gate    {
33490Sstevel@tonic-gate        $query_string = $2;
33500Sstevel@tonic-gate        $subpath = $1;
33510Sstevel@tonic-gate    }
33520Sstevel@tonic-gate    return { 'query_string' => $query_string, 'subpath' => $subpath };
33530Sstevel@tonic-gate}
33540Sstevel@tonic-gateEND_OF_FUNC
33550Sstevel@tonic-gate
33560Sstevel@tonic-gate#####
33570Sstevel@tonic-gate# subroutine: read_multipart
33580Sstevel@tonic-gate#
33590Sstevel@tonic-gate# Read multipart data and store it into our parameters.
33600Sstevel@tonic-gate# An interesting feature is that if any of the parts is a file, we
33610Sstevel@tonic-gate# create a temporary file and open up a filehandle on it so that the
33620Sstevel@tonic-gate# caller can read from it if necessary.
33630Sstevel@tonic-gate#####
33640Sstevel@tonic-gate'read_multipart' => <<'END_OF_FUNC',
33650Sstevel@tonic-gatesub read_multipart {
33660Sstevel@tonic-gate    my($self,$boundary,$length) = @_;
33670Sstevel@tonic-gate    my($buffer) = $self->new_MultipartBuffer($boundary,$length);
33680Sstevel@tonic-gate    return unless $buffer;
33690Sstevel@tonic-gate    my(%header,$body);
33700Sstevel@tonic-gate    my $filenumber = 0;
33710Sstevel@tonic-gate    while (!$buffer->eof) {
33720Sstevel@tonic-gate	%header = $buffer->readHeader;
33730Sstevel@tonic-gate
33740Sstevel@tonic-gate	unless (%header) {
33750Sstevel@tonic-gate	    $self->cgi_error("400 Bad request (malformed multipart POST)");
33760Sstevel@tonic-gate	    return;
33770Sstevel@tonic-gate	}
33780Sstevel@tonic-gate
3379*6287Sps156622	my($param)= $header{'Content-Disposition'}=~/ name="([^"]*)"/;
33800Sstevel@tonic-gate        $param .= $TAINTED;
33810Sstevel@tonic-gate
33820Sstevel@tonic-gate	# Bug:  Netscape doesn't escape quotation marks in file names!!!
3383*6287Sps156622	my($filename) = $header{'Content-Disposition'}=~/ filename="([^"]*)"/;
33840Sstevel@tonic-gate	# Test for Opera's multiple upload feature
33850Sstevel@tonic-gate	my($multipart) = ( defined( $header{'Content-Type'} ) &&
33860Sstevel@tonic-gate		$header{'Content-Type'} =~ /multipart\/mixed/ ) ?
33870Sstevel@tonic-gate		1 : 0;
33880Sstevel@tonic-gate
33890Sstevel@tonic-gate	# add this parameter to our list
33900Sstevel@tonic-gate	$self->add_parameter($param);
33910Sstevel@tonic-gate
33920Sstevel@tonic-gate	# If no filename specified, then just read the data and assign it
33930Sstevel@tonic-gate	# to our parameter list.
33940Sstevel@tonic-gate	if ( ( !defined($filename) || $filename eq '' ) && !$multipart ) {
33950Sstevel@tonic-gate	    my($value) = $buffer->readBody;
33960Sstevel@tonic-gate            $value .= $TAINTED;
33970Sstevel@tonic-gate	    push(@{$self->{$param}},$value);
33980Sstevel@tonic-gate	    next;
33990Sstevel@tonic-gate	}
34000Sstevel@tonic-gate
34010Sstevel@tonic-gate	my ($tmpfile,$tmp,$filehandle);
34020Sstevel@tonic-gate      UPLOADS: {
34030Sstevel@tonic-gate	  # If we get here, then we are dealing with a potentially large
34040Sstevel@tonic-gate	  # uploaded form.  Save the data to a temporary file, then open
34050Sstevel@tonic-gate	  # the file for reading.
34060Sstevel@tonic-gate
34070Sstevel@tonic-gate	  # skip the file if uploads disabled
34080Sstevel@tonic-gate	  if ($DISABLE_UPLOADS) {
34090Sstevel@tonic-gate	      while (defined($data = $buffer->read)) { }
34100Sstevel@tonic-gate	      last UPLOADS;
34110Sstevel@tonic-gate	  }
34120Sstevel@tonic-gate
34130Sstevel@tonic-gate	  # set the filename to some recognizable value
34140Sstevel@tonic-gate          if ( ( !defined($filename) || $filename eq '' ) && $multipart ) {
34150Sstevel@tonic-gate              $filename = "multipart/mixed";
34160Sstevel@tonic-gate          }
34170Sstevel@tonic-gate
34180Sstevel@tonic-gate	  # choose a relatively unpredictable tmpfile sequence number
3419667Sps156622          my $seqno = unpack("%16C*",join('',localtime,grep {defined $_} values %ENV));
34200Sstevel@tonic-gate          for (my $cnt=10;$cnt>0;$cnt--) {
34210Sstevel@tonic-gate	    next unless $tmpfile = new CGITempFile($seqno);
34220Sstevel@tonic-gate	    $tmp = $tmpfile->as_string;
34230Sstevel@tonic-gate	    last if defined($filehandle = Fh->new($filename,$tmp,$PRIVATE_TEMPFILES));
34240Sstevel@tonic-gate            $seqno += int rand(100);
34250Sstevel@tonic-gate          }
34260Sstevel@tonic-gate          die "CGI open of tmpfile: $!\n" unless defined $filehandle;
34270Sstevel@tonic-gate	  $CGI::DefaultClass->binmode($filehandle) if $CGI::needs_binmode
34280Sstevel@tonic-gate                     && defined fileno($filehandle);
34290Sstevel@tonic-gate
34300Sstevel@tonic-gate	  # if this is an multipart/mixed attachment, save the header
34310Sstevel@tonic-gate	  # together with the body for later parsing with an external
34320Sstevel@tonic-gate	  # MIME parser module
34330Sstevel@tonic-gate	  if ( $multipart ) {
34340Sstevel@tonic-gate	      foreach ( keys %header ) {
34350Sstevel@tonic-gate		  print $filehandle "$_: $header{$_}${CRLF}";
34360Sstevel@tonic-gate	      }
34370Sstevel@tonic-gate	      print $filehandle "${CRLF}";
34380Sstevel@tonic-gate	  }
34390Sstevel@tonic-gate
34400Sstevel@tonic-gate	  my ($data);
34410Sstevel@tonic-gate	  local($\) = '';
3442*6287Sps156622          my $totalbytes = 0;
34430Sstevel@tonic-gate          while (defined($data = $buffer->read)) {
34440Sstevel@tonic-gate              if (defined $self->{'.upload_hook'})
34450Sstevel@tonic-gate               {
34460Sstevel@tonic-gate                  $totalbytes += length($data);
34470Sstevel@tonic-gate                   &{$self->{'.upload_hook'}}($filename ,$data, $totalbytes, $self->{'.upload_data'});
34480Sstevel@tonic-gate              }
3449*6287Sps156622              print $filehandle $data if ($self->{'use_tempfile'});
34500Sstevel@tonic-gate          }
34510Sstevel@tonic-gate
34520Sstevel@tonic-gate	  # back up to beginning of file
34530Sstevel@tonic-gate	  seek($filehandle,0,0);
34540Sstevel@tonic-gate
34550Sstevel@tonic-gate      ## Close the filehandle if requested this allows a multipart MIME
34560Sstevel@tonic-gate      ## upload to contain many files, and we won't die due to too many
34570Sstevel@tonic-gate      ## open file handles. The user can access the files using the hash
34580Sstevel@tonic-gate      ## below.
34590Sstevel@tonic-gate      close $filehandle if $CLOSE_UPLOAD_FILES;
34600Sstevel@tonic-gate	  $CGI::DefaultClass->binmode($filehandle) if $CGI::needs_binmode;
34610Sstevel@tonic-gate
34620Sstevel@tonic-gate	  # Save some information about the uploaded file where we can get
34630Sstevel@tonic-gate	  # at it later.
3464*6287Sps156622	  # Use the typeglob as the key, as this is guaranteed to be
3465*6287Sps156622	  # unique for each filehandle.  Don't use the file descriptor as
3466*6287Sps156622	  # this will be re-used for each filehandle if the
3467*6287Sps156622	  # close_upload_files feature is used.
3468*6287Sps156622	  $self->{'.tmpfiles'}->{$$filehandle}= {
34690Sstevel@tonic-gate              hndl => $filehandle,
34700Sstevel@tonic-gate	      name => $tmpfile,
34710Sstevel@tonic-gate	      info => {%header},
34720Sstevel@tonic-gate	  };
34730Sstevel@tonic-gate	  push(@{$self->{$param}},$filehandle);
34740Sstevel@tonic-gate      }
34750Sstevel@tonic-gate    }
34760Sstevel@tonic-gate}
34770Sstevel@tonic-gateEND_OF_FUNC
34780Sstevel@tonic-gate
3479*6287Sps156622#####
3480*6287Sps156622# subroutine: read_multipart_related
3481*6287Sps156622#
3482*6287Sps156622# Read multipart/related data and store it into our parameters.  The
3483*6287Sps156622# first parameter sets the start of the data. The part identified by
3484*6287Sps156622# this Content-ID will not be stored as a file upload, but will be
3485*6287Sps156622# returned by this method.  All other parts will be available as file
3486*6287Sps156622# uploads accessible by their Content-ID
3487*6287Sps156622#####
3488*6287Sps156622'read_multipart_related' => <<'END_OF_FUNC',
3489*6287Sps156622sub read_multipart_related {
3490*6287Sps156622    my($self,$start,$boundary,$length) = @_;
3491*6287Sps156622    my($buffer) = $self->new_MultipartBuffer($boundary,$length);
3492*6287Sps156622    return unless $buffer;
3493*6287Sps156622    my(%header,$body);
3494*6287Sps156622    my $filenumber = 0;
3495*6287Sps156622    my $returnvalue;
3496*6287Sps156622    while (!$buffer->eof) {
3497*6287Sps156622	%header = $buffer->readHeader;
3498*6287Sps156622
3499*6287Sps156622	unless (%header) {
3500*6287Sps156622	    $self->cgi_error("400 Bad request (malformed multipart POST)");
3501*6287Sps156622	    return;
3502*6287Sps156622	}
3503*6287Sps156622
3504*6287Sps156622	my($param) = $header{'Content-ID'}=~/\<([^\>]*)\>/;
3505*6287Sps156622        $param .= $TAINTED;
3506*6287Sps156622
3507*6287Sps156622	# If this is the start part, then just read the data and assign it
3508*6287Sps156622	# to our return variable.
3509*6287Sps156622	if ( $param eq $start ) {
3510*6287Sps156622	    $returnvalue = $buffer->readBody;
3511*6287Sps156622            $returnvalue .= $TAINTED;
3512*6287Sps156622	    next;
3513*6287Sps156622	}
3514*6287Sps156622
3515*6287Sps156622	# add this parameter to our list
3516*6287Sps156622	$self->add_parameter($param);
3517*6287Sps156622
3518*6287Sps156622	my ($tmpfile,$tmp,$filehandle);
3519*6287Sps156622      UPLOADS: {
3520*6287Sps156622	  # If we get here, then we are dealing with a potentially large
3521*6287Sps156622	  # uploaded form.  Save the data to a temporary file, then open
3522*6287Sps156622	  # the file for reading.
3523*6287Sps156622
3524*6287Sps156622	  # skip the file if uploads disabled
3525*6287Sps156622	  if ($DISABLE_UPLOADS) {
3526*6287Sps156622	      while (defined($data = $buffer->read)) { }
3527*6287Sps156622	      last UPLOADS;
3528*6287Sps156622	  }
3529*6287Sps156622
3530*6287Sps156622	  # choose a relatively unpredictable tmpfile sequence number
3531*6287Sps156622          my $seqno = unpack("%16C*",join('',localtime,grep {defined $_} values %ENV));
3532*6287Sps156622          for (my $cnt=10;$cnt>0;$cnt--) {
3533*6287Sps156622	    next unless $tmpfile = new CGITempFile($seqno);
3534*6287Sps156622	    $tmp = $tmpfile->as_string;
3535*6287Sps156622	    last if defined($filehandle = Fh->new($param,$tmp,$PRIVATE_TEMPFILES));
3536*6287Sps156622            $seqno += int rand(100);
3537*6287Sps156622          }
3538*6287Sps156622          die "CGI open of tmpfile: $!\n" unless defined $filehandle;
3539*6287Sps156622	  $CGI::DefaultClass->binmode($filehandle) if $CGI::needs_binmode
3540*6287Sps156622                     && defined fileno($filehandle);
3541*6287Sps156622
3542*6287Sps156622	  my ($data);
3543*6287Sps156622	  local($\) = '';
3544*6287Sps156622          my $totalbytes;
3545*6287Sps156622          while (defined($data = $buffer->read)) {
3546*6287Sps156622              if (defined $self->{'.upload_hook'})
3547*6287Sps156622               {
3548*6287Sps156622                  $totalbytes += length($data);
3549*6287Sps156622                   &{$self->{'.upload_hook'}}($param ,$data, $totalbytes, $self->{'.upload_data'});
3550*6287Sps156622              }
3551*6287Sps156622              print $filehandle $data if ($self->{'use_tempfile'});
3552*6287Sps156622          }
3553*6287Sps156622
3554*6287Sps156622	  # back up to beginning of file
3555*6287Sps156622	  seek($filehandle,0,0);
3556*6287Sps156622
3557*6287Sps156622      ## Close the filehandle if requested this allows a multipart MIME
3558*6287Sps156622      ## upload to contain many files, and we won't die due to too many
3559*6287Sps156622      ## open file handles. The user can access the files using the hash
3560*6287Sps156622      ## below.
3561*6287Sps156622      close $filehandle if $CLOSE_UPLOAD_FILES;
3562*6287Sps156622	  $CGI::DefaultClass->binmode($filehandle) if $CGI::needs_binmode;
3563*6287Sps156622
3564*6287Sps156622	  # Save some information about the uploaded file where we can get
3565*6287Sps156622	  # at it later.
3566*6287Sps156622	  # Use the typeglob as the key, as this is guaranteed to be
3567*6287Sps156622	  # unique for each filehandle.  Don't use the file descriptor as
3568*6287Sps156622	  # this will be re-used for each filehandle if the
3569*6287Sps156622	  # close_upload_files feature is used.
3570*6287Sps156622	  $self->{'.tmpfiles'}->{$$filehandle}= {
3571*6287Sps156622              hndl => $filehandle,
3572*6287Sps156622	      name => $tmpfile,
3573*6287Sps156622	      info => {%header},
3574*6287Sps156622	  };
3575*6287Sps156622	  push(@{$self->{$param}},$filehandle);
3576*6287Sps156622      }
3577*6287Sps156622    }
3578*6287Sps156622    return $returnvalue;
3579*6287Sps156622}
3580*6287Sps156622END_OF_FUNC
3581*6287Sps156622
3582*6287Sps156622
35830Sstevel@tonic-gate'upload' =><<'END_OF_FUNC',
35840Sstevel@tonic-gatesub upload {
35850Sstevel@tonic-gate    my($self,$param_name) = self_or_default(@_);
3586*6287Sps156622    my @param = grep {ref($_) && defined(fileno($_))} $self->param($param_name);
35870Sstevel@tonic-gate    return unless @param;
35880Sstevel@tonic-gate    return wantarray ? @param : $param[0];
35890Sstevel@tonic-gate}
35900Sstevel@tonic-gateEND_OF_FUNC
35910Sstevel@tonic-gate
35920Sstevel@tonic-gate'tmpFileName' => <<'END_OF_FUNC',
35930Sstevel@tonic-gatesub tmpFileName {
35940Sstevel@tonic-gate    my($self,$filename) = self_or_default(@_);
3595*6287Sps156622    return $self->{'.tmpfiles'}->{$$filename}->{name} ?
3596*6287Sps156622	$self->{'.tmpfiles'}->{$$filename}->{name}->as_string
35970Sstevel@tonic-gate	    : '';
35980Sstevel@tonic-gate}
35990Sstevel@tonic-gateEND_OF_FUNC
36000Sstevel@tonic-gate
36010Sstevel@tonic-gate'uploadInfo' => <<'END_OF_FUNC',
36020Sstevel@tonic-gatesub uploadInfo {
36030Sstevel@tonic-gate    my($self,$filename) = self_or_default(@_);
3604*6287Sps156622    return $self->{'.tmpfiles'}->{$$filename}->{info};
36050Sstevel@tonic-gate}
36060Sstevel@tonic-gateEND_OF_FUNC
36070Sstevel@tonic-gate
36080Sstevel@tonic-gate# internal routine, don't use
36090Sstevel@tonic-gate'_set_values_and_labels' => <<'END_OF_FUNC',
36100Sstevel@tonic-gatesub _set_values_and_labels {
36110Sstevel@tonic-gate    my $self = shift;
36120Sstevel@tonic-gate    my ($v,$l,$n) = @_;
36130Sstevel@tonic-gate    $$l = $v if ref($v) eq 'HASH' && !ref($$l);
36140Sstevel@tonic-gate    return $self->param($n) if !defined($v);
36150Sstevel@tonic-gate    return $v if !ref($v);
36160Sstevel@tonic-gate    return ref($v) eq 'HASH' ? keys %$v : @$v;
36170Sstevel@tonic-gate}
36180Sstevel@tonic-gateEND_OF_FUNC
36190Sstevel@tonic-gate
36200Sstevel@tonic-gate# internal routine, don't use
36210Sstevel@tonic-gate'_set_attributes' => <<'END_OF_FUNC',
36220Sstevel@tonic-gatesub _set_attributes {
36230Sstevel@tonic-gate    my $self = shift;
36240Sstevel@tonic-gate    my($element, $attributes) = @_;
36250Sstevel@tonic-gate    return '' unless defined($attributes->{$element});
36260Sstevel@tonic-gate    $attribs = ' ';
36270Sstevel@tonic-gate    foreach my $attrib (keys %{$attributes->{$element}}) {
3628667Sps156622        (my $clean_attrib = $attrib) =~ s/^-//;
3629667Sps156622        $attribs .= "@{[lc($clean_attrib)]}=\"$attributes->{$element}{$attrib}\" ";
36300Sstevel@tonic-gate    }
36310Sstevel@tonic-gate    $attribs =~ s/ $//;
36320Sstevel@tonic-gate    return $attribs;
36330Sstevel@tonic-gate}
36340Sstevel@tonic-gateEND_OF_FUNC
36350Sstevel@tonic-gate
36360Sstevel@tonic-gate'_compile_all' => <<'END_OF_FUNC',
36370Sstevel@tonic-gatesub _compile_all {
36380Sstevel@tonic-gate    foreach (@_) {
36390Sstevel@tonic-gate	next if defined(&$_);
36400Sstevel@tonic-gate	$AUTOLOAD = "CGI::$_";
36410Sstevel@tonic-gate	_compile();
36420Sstevel@tonic-gate    }
36430Sstevel@tonic-gate}
36440Sstevel@tonic-gateEND_OF_FUNC
36450Sstevel@tonic-gate
36460Sstevel@tonic-gate);
36470Sstevel@tonic-gateEND_OF_AUTOLOAD
36480Sstevel@tonic-gate;
36490Sstevel@tonic-gate
36500Sstevel@tonic-gate#########################################################
36510Sstevel@tonic-gate# Globals and stubs for other packages that we use.
36520Sstevel@tonic-gate#########################################################
36530Sstevel@tonic-gate
36540Sstevel@tonic-gate################### Fh -- lightweight filehandle ###############
36550Sstevel@tonic-gatepackage Fh;
36560Sstevel@tonic-gateuse overload
36570Sstevel@tonic-gate    '""'  => \&asString,
36580Sstevel@tonic-gate    'cmp' => \&compare,
36590Sstevel@tonic-gate    'fallback'=>1;
36600Sstevel@tonic-gate
36610Sstevel@tonic-gate$FH='fh00000';
36620Sstevel@tonic-gate
36630Sstevel@tonic-gate*Fh::AUTOLOAD = \&CGI::AUTOLOAD;
36640Sstevel@tonic-gate
3665667Sps156622sub DESTROY {
3666667Sps156622    my $self = shift;
3667667Sps156622    close $self;
3668667Sps156622}
3669667Sps156622
36700Sstevel@tonic-gate$AUTOLOADED_ROUTINES = '';      # prevent -w error
36710Sstevel@tonic-gate$AUTOLOADED_ROUTINES=<<'END_OF_AUTOLOAD';
36720Sstevel@tonic-gate%SUBS =  (
36730Sstevel@tonic-gate'asString' => <<'END_OF_FUNC',
36740Sstevel@tonic-gatesub asString {
36750Sstevel@tonic-gate    my $self = shift;
36760Sstevel@tonic-gate    # get rid of package name
36770Sstevel@tonic-gate    (my $i = $$self) =~ s/^\*(\w+::fh\d{5})+//;
36780Sstevel@tonic-gate    $i =~ s/%(..)/ chr(hex($1)) /eg;
36790Sstevel@tonic-gate    return $i.$CGI::TAINTED;
36800Sstevel@tonic-gate# BEGIN DEAD CODE
36810Sstevel@tonic-gate# This was an extremely clever patch that allowed "use strict refs".
36820Sstevel@tonic-gate# Unfortunately it relied on another bug that caused leaky file descriptors.
36830Sstevel@tonic-gate# The underlying bug has been fixed, so this no longer works.  However
36840Sstevel@tonic-gate# "strict refs" still works for some reason.
36850Sstevel@tonic-gate#    my $self = shift;
36860Sstevel@tonic-gate#    return ${*{$self}{SCALAR}};
36870Sstevel@tonic-gate# END DEAD CODE
36880Sstevel@tonic-gate}
36890Sstevel@tonic-gateEND_OF_FUNC
36900Sstevel@tonic-gate
36910Sstevel@tonic-gate'compare' => <<'END_OF_FUNC',
36920Sstevel@tonic-gatesub compare {
36930Sstevel@tonic-gate    my $self = shift;
36940Sstevel@tonic-gate    my $value = shift;
36950Sstevel@tonic-gate    return "$self" cmp $value;
36960Sstevel@tonic-gate}
36970Sstevel@tonic-gateEND_OF_FUNC
36980Sstevel@tonic-gate
36990Sstevel@tonic-gate'new'  => <<'END_OF_FUNC',
37000Sstevel@tonic-gatesub new {
37010Sstevel@tonic-gate    my($pack,$name,$file,$delete) = @_;
37020Sstevel@tonic-gate    _setup_symbols(@SAVED_SYMBOLS) if @SAVED_SYMBOLS;
37030Sstevel@tonic-gate    require Fcntl unless defined &Fcntl::O_RDWR;
37040Sstevel@tonic-gate    (my $safename = $name) =~ s/([':%])/ sprintf '%%%02X', ord $1 /eg;
37050Sstevel@tonic-gate    my $fv = ++$FH . $safename;
37060Sstevel@tonic-gate    my $ref = \*{"Fh::$fv"};
3707*6287Sps156622    $file =~ m!^([a-zA-Z0-9_\+ \'\":/.\$\\-]+)$! || return;
37080Sstevel@tonic-gate    my $safe = $1;
37090Sstevel@tonic-gate    sysopen($ref,$safe,Fcntl::O_RDWR()|Fcntl::O_CREAT()|Fcntl::O_EXCL(),0600) || return;
37100Sstevel@tonic-gate    unlink($safe) if $delete;
37110Sstevel@tonic-gate    CORE::delete $Fh::{$fv};
37120Sstevel@tonic-gate    return bless $ref,$pack;
37130Sstevel@tonic-gate}
37140Sstevel@tonic-gateEND_OF_FUNC
37150Sstevel@tonic-gate
37160Sstevel@tonic-gate);
37170Sstevel@tonic-gateEND_OF_AUTOLOAD
37180Sstevel@tonic-gate
37190Sstevel@tonic-gate######################## MultipartBuffer ####################
37200Sstevel@tonic-gatepackage MultipartBuffer;
37210Sstevel@tonic-gate
37220Sstevel@tonic-gateuse constant DEBUG => 0;
37230Sstevel@tonic-gate
37240Sstevel@tonic-gate# how many bytes to read at a time.  We use
37250Sstevel@tonic-gate# a 4K buffer by default.
37260Sstevel@tonic-gate$INITIAL_FILLUNIT = 1024 * 4;
37270Sstevel@tonic-gate$TIMEOUT = 240*60;       # 4 hour timeout for big files
37280Sstevel@tonic-gate$SPIN_LOOP_MAX = 2000;  # bug fix for some Netscape servers
37290Sstevel@tonic-gate$CRLF=$CGI::CRLF;
37300Sstevel@tonic-gate
37310Sstevel@tonic-gate#reuse the autoload function
37320Sstevel@tonic-gate*MultipartBuffer::AUTOLOAD = \&CGI::AUTOLOAD;
37330Sstevel@tonic-gate
37340Sstevel@tonic-gate# avoid autoloader warnings
37350Sstevel@tonic-gatesub DESTROY {}
37360Sstevel@tonic-gate
37370Sstevel@tonic-gate###############################################################################
37380Sstevel@tonic-gate################# THESE FUNCTIONS ARE AUTOLOADED ON DEMAND ####################
37390Sstevel@tonic-gate###############################################################################
37400Sstevel@tonic-gate$AUTOLOADED_ROUTINES = '';      # prevent -w error
37410Sstevel@tonic-gate$AUTOLOADED_ROUTINES=<<'END_OF_AUTOLOAD';
37420Sstevel@tonic-gate%SUBS =  (
37430Sstevel@tonic-gate
37440Sstevel@tonic-gate'new' => <<'END_OF_FUNC',
37450Sstevel@tonic-gatesub new {
37460Sstevel@tonic-gate    my($package,$interface,$boundary,$length) = @_;
37470Sstevel@tonic-gate    $FILLUNIT = $INITIAL_FILLUNIT;
37480Sstevel@tonic-gate    $CGI::DefaultClass->binmode($IN); # if $CGI::needs_binmode;  # just do it always
3749667Sps156622
37500Sstevel@tonic-gate    # If the user types garbage into the file upload field,
37510Sstevel@tonic-gate    # then Netscape passes NOTHING to the server (not good).
37520Sstevel@tonic-gate    # We may hang on this read in that case. So we implement
37530Sstevel@tonic-gate    # a read timeout.  If nothing is ready to read
37540Sstevel@tonic-gate    # by then, we return.
37550Sstevel@tonic-gate
37560Sstevel@tonic-gate    # Netscape seems to be a little bit unreliable
37570Sstevel@tonic-gate    # about providing boundary strings.
37580Sstevel@tonic-gate    my $boundary_read = 0;
37590Sstevel@tonic-gate    if ($boundary) {
37600Sstevel@tonic-gate
37610Sstevel@tonic-gate	# Under the MIME spec, the boundary consists of the
37620Sstevel@tonic-gate	# characters "--" PLUS the Boundary string
37630Sstevel@tonic-gate
37640Sstevel@tonic-gate	# BUG: IE 3.01 on the Macintosh uses just the boundary -- not
37650Sstevel@tonic-gate	# the two extra hyphens.  We do a special case here on the user-agent!!!!
37660Sstevel@tonic-gate	$boundary = "--$boundary" unless CGI::user_agent('MSIE\s+3\.0[12];\s*Mac|DreamPassport');
37670Sstevel@tonic-gate
37680Sstevel@tonic-gate    } else { # otherwise we find it ourselves
37690Sstevel@tonic-gate	my($old);
37700Sstevel@tonic-gate	($old,$/) = ($/,$CRLF); # read a CRLF-delimited line
37710Sstevel@tonic-gate	$boundary = <STDIN>;      # BUG: This won't work correctly under mod_perl
37720Sstevel@tonic-gate	$length -= length($boundary);
37730Sstevel@tonic-gate	chomp($boundary);               # remove the CRLF
37740Sstevel@tonic-gate	$/ = $old;                      # restore old line separator
37750Sstevel@tonic-gate        $boundary_read++;
37760Sstevel@tonic-gate    }
37770Sstevel@tonic-gate
37780Sstevel@tonic-gate    my $self = {LENGTH=>$length,
3779667Sps156622		CHUNKED=>!defined $length,
37800Sstevel@tonic-gate		BOUNDARY=>$boundary,
37810Sstevel@tonic-gate		INTERFACE=>$interface,
37820Sstevel@tonic-gate		BUFFER=>'',
37830Sstevel@tonic-gate	    };
37840Sstevel@tonic-gate
37850Sstevel@tonic-gate    $FILLUNIT = length($boundary)
37860Sstevel@tonic-gate	if length($boundary) > $FILLUNIT;
37870Sstevel@tonic-gate
37880Sstevel@tonic-gate    my $retval = bless $self,ref $package || $package;
37890Sstevel@tonic-gate
37900Sstevel@tonic-gate    # Read the preamble and the topmost (boundary) line plus the CRLF.
37910Sstevel@tonic-gate    unless ($boundary_read) {
37920Sstevel@tonic-gate      while ($self->read(0)) { }
37930Sstevel@tonic-gate    }
37940Sstevel@tonic-gate    die "Malformed multipart POST: data truncated\n" if $self->eof;
37950Sstevel@tonic-gate
37960Sstevel@tonic-gate    return $retval;
37970Sstevel@tonic-gate}
37980Sstevel@tonic-gateEND_OF_FUNC
37990Sstevel@tonic-gate
38000Sstevel@tonic-gate'readHeader' => <<'END_OF_FUNC',
38010Sstevel@tonic-gatesub readHeader {
38020Sstevel@tonic-gate    my($self) = @_;
38030Sstevel@tonic-gate    my($end);
38040Sstevel@tonic-gate    my($ok) = 0;
38050Sstevel@tonic-gate    my($bad) = 0;
38060Sstevel@tonic-gate
38070Sstevel@tonic-gate    local($CRLF) = "\015\012" if $CGI::OS eq 'VMS' || $CGI::EBCDIC;
38080Sstevel@tonic-gate
38090Sstevel@tonic-gate    do {
38100Sstevel@tonic-gate	$self->fillBuffer($FILLUNIT);
38110Sstevel@tonic-gate	$ok++ if ($end = index($self->{BUFFER},"${CRLF}${CRLF}")) >= 0;
38120Sstevel@tonic-gate	$ok++ if $self->{BUFFER} eq '';
38130Sstevel@tonic-gate	$bad++ if !$ok && $self->{LENGTH} <= 0;
38140Sstevel@tonic-gate	# this was a bad idea
38150Sstevel@tonic-gate	# $FILLUNIT *= 2 if length($self->{BUFFER}) >= $FILLUNIT;
38160Sstevel@tonic-gate    } until $ok || $bad;
38170Sstevel@tonic-gate    return () if $bad;
38180Sstevel@tonic-gate
38190Sstevel@tonic-gate    #EBCDIC NOTE: translate header into EBCDIC, but watch out for continuation lines!
38200Sstevel@tonic-gate
38210Sstevel@tonic-gate    my($header) = substr($self->{BUFFER},0,$end+2);
38220Sstevel@tonic-gate    substr($self->{BUFFER},0,$end+4) = '';
38230Sstevel@tonic-gate    my %return;
38240Sstevel@tonic-gate
38250Sstevel@tonic-gate    if ($CGI::EBCDIC) {
38260Sstevel@tonic-gate      warn "untranslated header=$header\n" if DEBUG;
38270Sstevel@tonic-gate      $header = CGI::Util::ascii2ebcdic($header);
38280Sstevel@tonic-gate      warn "translated header=$header\n" if DEBUG;
38290Sstevel@tonic-gate    }
38300Sstevel@tonic-gate
38310Sstevel@tonic-gate    # See RFC 2045 Appendix A and RFC 822 sections 3.4.8
38320Sstevel@tonic-gate    #   (Folding Long Header Fields), 3.4.3 (Comments)
38330Sstevel@tonic-gate    #   and 3.4.5 (Quoted-Strings).
38340Sstevel@tonic-gate
38350Sstevel@tonic-gate    my $token = '[-\w!\#$%&\'*+.^_\`|{}~]';
38360Sstevel@tonic-gate    $header=~s/$CRLF\s+/ /og;		# merge continuation lines
38370Sstevel@tonic-gate
38380Sstevel@tonic-gate    while ($header=~/($token+):\s+([^$CRLF]*)/mgox) {
38390Sstevel@tonic-gate        my ($field_name,$field_value) = ($1,$2);
38400Sstevel@tonic-gate	$field_name =~ s/\b(\w)/uc($1)/eg; #canonicalize
38410Sstevel@tonic-gate	$return{$field_name}=$field_value;
38420Sstevel@tonic-gate    }
38430Sstevel@tonic-gate    return %return;
38440Sstevel@tonic-gate}
38450Sstevel@tonic-gateEND_OF_FUNC
38460Sstevel@tonic-gate
38470Sstevel@tonic-gate# This reads and returns the body as a single scalar value.
38480Sstevel@tonic-gate'readBody' => <<'END_OF_FUNC',
38490Sstevel@tonic-gatesub readBody {
38500Sstevel@tonic-gate    my($self) = @_;
38510Sstevel@tonic-gate    my($data);
38520Sstevel@tonic-gate    my($returnval)='';
38530Sstevel@tonic-gate
38540Sstevel@tonic-gate    #EBCDIC NOTE: want to translate returnval into EBCDIC HERE
38550Sstevel@tonic-gate
38560Sstevel@tonic-gate    while (defined($data = $self->read)) {
38570Sstevel@tonic-gate	$returnval .= $data;
38580Sstevel@tonic-gate    }
38590Sstevel@tonic-gate
38600Sstevel@tonic-gate    if ($CGI::EBCDIC) {
38610Sstevel@tonic-gate      warn "untranslated body=$returnval\n" if DEBUG;
38620Sstevel@tonic-gate      $returnval = CGI::Util::ascii2ebcdic($returnval);
38630Sstevel@tonic-gate      warn "translated body=$returnval\n"   if DEBUG;
38640Sstevel@tonic-gate    }
38650Sstevel@tonic-gate    return $returnval;
38660Sstevel@tonic-gate}
38670Sstevel@tonic-gateEND_OF_FUNC
38680Sstevel@tonic-gate
38690Sstevel@tonic-gate# This will read $bytes or until the boundary is hit, whichever happens
38700Sstevel@tonic-gate# first.  After the boundary is hit, we return undef.  The next read will
38710Sstevel@tonic-gate# skip over the boundary and begin reading again;
38720Sstevel@tonic-gate'read' => <<'END_OF_FUNC',
38730Sstevel@tonic-gatesub read {
38740Sstevel@tonic-gate    my($self,$bytes) = @_;
38750Sstevel@tonic-gate
38760Sstevel@tonic-gate    # default number of bytes to read
38770Sstevel@tonic-gate    $bytes = $bytes || $FILLUNIT;
38780Sstevel@tonic-gate
38790Sstevel@tonic-gate    # Fill up our internal buffer in such a way that the boundary
38800Sstevel@tonic-gate    # is never split between reads.
38810Sstevel@tonic-gate    $self->fillBuffer($bytes);
38820Sstevel@tonic-gate
38830Sstevel@tonic-gate    my $boundary_start = $CGI::EBCDIC ? CGI::Util::ebcdic2ascii($self->{BOUNDARY})      : $self->{BOUNDARY};
38840Sstevel@tonic-gate    my $boundary_end   = $CGI::EBCDIC ? CGI::Util::ebcdic2ascii($self->{BOUNDARY}.'--') : $self->{BOUNDARY}.'--';
38850Sstevel@tonic-gate
38860Sstevel@tonic-gate    # Find the boundary in the buffer (it may not be there).
38870Sstevel@tonic-gate    my $start = index($self->{BUFFER},$boundary_start);
38880Sstevel@tonic-gate
38890Sstevel@tonic-gate    warn "boundary=$self->{BOUNDARY} length=$self->{LENGTH} start=$start\n" if DEBUG;
3890667Sps156622
38910Sstevel@tonic-gate    # protect against malformed multipart POST operations
3892667Sps156622    die "Malformed multipart POST\n" unless $self->{CHUNKED} || ($start >= 0 || $self->{LENGTH} > 0);
38930Sstevel@tonic-gate
38940Sstevel@tonic-gate    #EBCDIC NOTE: want to translate boundary search into ASCII here.
38950Sstevel@tonic-gate
38960Sstevel@tonic-gate    # If the boundary begins the data, then skip past it
38970Sstevel@tonic-gate    # and return undef.
38980Sstevel@tonic-gate    if ($start == 0) {
38990Sstevel@tonic-gate
39000Sstevel@tonic-gate	# clear us out completely if we've hit the last boundary.
39010Sstevel@tonic-gate	if (index($self->{BUFFER},$boundary_end)==0) {
39020Sstevel@tonic-gate	    $self->{BUFFER}='';
39030Sstevel@tonic-gate	    $self->{LENGTH}=0;
39040Sstevel@tonic-gate	    return undef;
39050Sstevel@tonic-gate	}
39060Sstevel@tonic-gate
39070Sstevel@tonic-gate	# just remove the boundary.
39080Sstevel@tonic-gate	substr($self->{BUFFER},0,length($boundary_start))='';
39090Sstevel@tonic-gate        $self->{BUFFER} =~ s/^\012\015?//;
39100Sstevel@tonic-gate	return undef;
39110Sstevel@tonic-gate    }
39120Sstevel@tonic-gate
39130Sstevel@tonic-gate    my $bytesToReturn;
39140Sstevel@tonic-gate    if ($start > 0) {           # read up to the boundary
39150Sstevel@tonic-gate        $bytesToReturn = $start-2 > $bytes ? $bytes : $start;
39160Sstevel@tonic-gate    } else {    # read the requested number of bytes
39170Sstevel@tonic-gate	# leave enough bytes in the buffer to allow us to read
39180Sstevel@tonic-gate	# the boundary.  Thanks to Kevin Hendrick for finding
39190Sstevel@tonic-gate	# this one.
39200Sstevel@tonic-gate	$bytesToReturn = $bytes - (length($boundary_start)+1);
39210Sstevel@tonic-gate    }
39220Sstevel@tonic-gate
39230Sstevel@tonic-gate    my $returnval=substr($self->{BUFFER},0,$bytesToReturn);
39240Sstevel@tonic-gate    substr($self->{BUFFER},0,$bytesToReturn)='';
39250Sstevel@tonic-gate
39260Sstevel@tonic-gate    # If we hit the boundary, remove the CRLF from the end.
39270Sstevel@tonic-gate    return ($bytesToReturn==$start)
39280Sstevel@tonic-gate           ? substr($returnval,0,-2) : $returnval;
39290Sstevel@tonic-gate}
39300Sstevel@tonic-gateEND_OF_FUNC
39310Sstevel@tonic-gate
39320Sstevel@tonic-gate
39330Sstevel@tonic-gate# This fills up our internal buffer in such a way that the
39340Sstevel@tonic-gate# boundary is never split between reads
39350Sstevel@tonic-gate'fillBuffer' => <<'END_OF_FUNC',
39360Sstevel@tonic-gatesub fillBuffer {
39370Sstevel@tonic-gate    my($self,$bytes) = @_;
3938667Sps156622    return unless $self->{CHUNKED} || $self->{LENGTH};
39390Sstevel@tonic-gate
39400Sstevel@tonic-gate    my($boundaryLength) = length($self->{BOUNDARY});
39410Sstevel@tonic-gate    my($bufferLength) = length($self->{BUFFER});
39420Sstevel@tonic-gate    my($bytesToRead) = $bytes - $bufferLength + $boundaryLength + 2;
3943667Sps156622    $bytesToRead = $self->{LENGTH} if !$self->{CHUNKED} && $self->{LENGTH} < $bytesToRead;
39440Sstevel@tonic-gate
39450Sstevel@tonic-gate    # Try to read some data.  We may hang here if the browser is screwed up.
39460Sstevel@tonic-gate    my $bytesRead = $self->{INTERFACE}->read_from_client(\$self->{BUFFER},
39470Sstevel@tonic-gate							 $bytesToRead,
39480Sstevel@tonic-gate							 $bufferLength);
39490Sstevel@tonic-gate    warn "bytesToRead=$bytesToRead, bufferLength=$bufferLength, buffer=$self->{BUFFER}\n" if DEBUG;
39500Sstevel@tonic-gate    $self->{BUFFER} = '' unless defined $self->{BUFFER};
39510Sstevel@tonic-gate
39520Sstevel@tonic-gate    # An apparent bug in the Apache server causes the read()
39530Sstevel@tonic-gate    # to return zero bytes repeatedly without blocking if the
39540Sstevel@tonic-gate    # remote user aborts during a file transfer.  I don't know how
39550Sstevel@tonic-gate    # they manage this, but the workaround is to abort if we get
39560Sstevel@tonic-gate    # more than SPIN_LOOP_MAX consecutive zero reads.
3957667Sps156622    if ($bytesRead <= 0) {
39580Sstevel@tonic-gate	die  "CGI.pm: Server closed socket during multipart read (client aborted?).\n"
39590Sstevel@tonic-gate	    if ($self->{ZERO_LOOP_COUNTER}++ >= $SPIN_LOOP_MAX);
39600Sstevel@tonic-gate    } else {
39610Sstevel@tonic-gate	$self->{ZERO_LOOP_COUNTER}=0;
39620Sstevel@tonic-gate    }
39630Sstevel@tonic-gate
3964667Sps156622    $self->{LENGTH} -= $bytesRead if !$self->{CHUNKED} && $bytesRead;
39650Sstevel@tonic-gate}
39660Sstevel@tonic-gateEND_OF_FUNC
39670Sstevel@tonic-gate
39680Sstevel@tonic-gate
39690Sstevel@tonic-gate# Return true when we've finished reading
39700Sstevel@tonic-gate'eof' => <<'END_OF_FUNC'
39710Sstevel@tonic-gatesub eof {
39720Sstevel@tonic-gate    my($self) = @_;
39730Sstevel@tonic-gate    return 1 if (length($self->{BUFFER}) == 0)
39740Sstevel@tonic-gate		 && ($self->{LENGTH} <= 0);
39750Sstevel@tonic-gate    undef;
39760Sstevel@tonic-gate}
39770Sstevel@tonic-gateEND_OF_FUNC
39780Sstevel@tonic-gate
39790Sstevel@tonic-gate);
39800Sstevel@tonic-gateEND_OF_AUTOLOAD
39810Sstevel@tonic-gate
39820Sstevel@tonic-gate####################################################################################
39830Sstevel@tonic-gate################################## TEMPORARY FILES #################################
39840Sstevel@tonic-gate####################################################################################
39850Sstevel@tonic-gatepackage CGITempFile;
39860Sstevel@tonic-gate
39870Sstevel@tonic-gatesub find_tempdir {
39880Sstevel@tonic-gate  $SL = $CGI::SL;
39890Sstevel@tonic-gate  $MAC = $CGI::OS eq 'MACINTOSH';
39900Sstevel@tonic-gate  my ($vol) = $MAC ? MacPerl::Volumes() =~ /:(.*)/ : "";
3991*6287Sps156622  unless (defined $TMPDIRECTORY) {
39920Sstevel@tonic-gate    @TEMP=("${SL}usr${SL}tmp","${SL}var${SL}tmp",
39930Sstevel@tonic-gate	   "C:${SL}temp","${SL}tmp","${SL}temp",
39940Sstevel@tonic-gate	   "${vol}${SL}Temporary Items",
39950Sstevel@tonic-gate           "${SL}WWW_ROOT", "${SL}SYS\$SCRATCH",
39960Sstevel@tonic-gate	   "C:${SL}system${SL}temp");
39970Sstevel@tonic-gate    unshift(@TEMP,$ENV{'TMPDIR'}) if defined $ENV{'TMPDIR'};
39980Sstevel@tonic-gate
39990Sstevel@tonic-gate    # this feature was supposed to provide per-user tmpfiles, but
40000Sstevel@tonic-gate    # it is problematic.
40010Sstevel@tonic-gate    #    unshift(@TEMP,(getpwuid($<))[7].'/tmp') if $CGI::OS eq 'UNIX';
40020Sstevel@tonic-gate    # Rob: getpwuid() is unfortunately UNIX specific. On brain dead OS'es this
40030Sstevel@tonic-gate    #    : can generate a 'getpwuid() not implemented' exception, even though
40040Sstevel@tonic-gate    #    : it's never called.  Found under DOS/Win with the DJGPP perl port.
40050Sstevel@tonic-gate    #    : Refer to getpwuid() only at run-time if we're fortunate and have  UNIX.
40060Sstevel@tonic-gate    # unshift(@TEMP,(eval {(getpwuid($>))[7]}).'/tmp') if $CGI::OS eq 'UNIX' and $> != 0;
40070Sstevel@tonic-gate
40080Sstevel@tonic-gate    foreach (@TEMP) {
40090Sstevel@tonic-gate      do {$TMPDIRECTORY = $_; last} if -d $_ && -w _;
40100Sstevel@tonic-gate    }
40110Sstevel@tonic-gate  }
40120Sstevel@tonic-gate  $TMPDIRECTORY  = $MAC ? "" : "." unless $TMPDIRECTORY;
40130Sstevel@tonic-gate}
40140Sstevel@tonic-gate
40150Sstevel@tonic-gatefind_tempdir();
40160Sstevel@tonic-gate
40170Sstevel@tonic-gate$MAXTRIES = 5000;
40180Sstevel@tonic-gate
40190Sstevel@tonic-gate# cute feature, but overload implementation broke it
40200Sstevel@tonic-gate# %OVERLOAD = ('""'=>'as_string');
40210Sstevel@tonic-gate*CGITempFile::AUTOLOAD = \&CGI::AUTOLOAD;
40220Sstevel@tonic-gate
40230Sstevel@tonic-gatesub DESTROY {
40240Sstevel@tonic-gate    my($self) = @_;
40250Sstevel@tonic-gate    $$self =~ m!^([a-zA-Z0-9_ \'\":/.\$\\-]+)$! || return;
40260Sstevel@tonic-gate    my $safe = $1;             # untaint operation
40270Sstevel@tonic-gate    unlink $safe;              # get rid of the file
40280Sstevel@tonic-gate}
40290Sstevel@tonic-gate
40300Sstevel@tonic-gate###############################################################################
40310Sstevel@tonic-gate################# THESE FUNCTIONS ARE AUTOLOADED ON DEMAND ####################
40320Sstevel@tonic-gate###############################################################################
40330Sstevel@tonic-gate$AUTOLOADED_ROUTINES = '';      # prevent -w error
40340Sstevel@tonic-gate$AUTOLOADED_ROUTINES=<<'END_OF_AUTOLOAD';
40350Sstevel@tonic-gate%SUBS = (
40360Sstevel@tonic-gate
40370Sstevel@tonic-gate'new' => <<'END_OF_FUNC',
40380Sstevel@tonic-gatesub new {
40390Sstevel@tonic-gate    my($package,$sequence) = @_;
40400Sstevel@tonic-gate    my $filename;
40410Sstevel@tonic-gate    find_tempdir() unless -w $TMPDIRECTORY;
40420Sstevel@tonic-gate    for (my $i = 0; $i < $MAXTRIES; $i++) {
40430Sstevel@tonic-gate	last if ! -f ($filename = sprintf("${TMPDIRECTORY}${SL}CGItemp%d",$sequence++));
40440Sstevel@tonic-gate    }
40450Sstevel@tonic-gate    # check that it is a more-or-less valid filename
4046*6287Sps156622    return unless $filename =~ m!^([a-zA-Z0-9_\+ \'\":/.\$\\-]+)$!;
40470Sstevel@tonic-gate    # this used to untaint, now it doesn't
40480Sstevel@tonic-gate    # $filename = $1;
40490Sstevel@tonic-gate    return bless \$filename;
40500Sstevel@tonic-gate}
40510Sstevel@tonic-gateEND_OF_FUNC
40520Sstevel@tonic-gate
40530Sstevel@tonic-gate'as_string' => <<'END_OF_FUNC'
40540Sstevel@tonic-gatesub as_string {
40550Sstevel@tonic-gate    my($self) = @_;
40560Sstevel@tonic-gate    return $$self;
40570Sstevel@tonic-gate}
40580Sstevel@tonic-gateEND_OF_FUNC
40590Sstevel@tonic-gate
40600Sstevel@tonic-gate);
40610Sstevel@tonic-gateEND_OF_AUTOLOAD
40620Sstevel@tonic-gate
40630Sstevel@tonic-gatepackage CGI;
40640Sstevel@tonic-gate
40650Sstevel@tonic-gate# We get a whole bunch of warnings about "possibly uninitialized variables"
40660Sstevel@tonic-gate# when running with the -w switch.  Touch them all once to get rid of the
40670Sstevel@tonic-gate# warnings.  This is ugly and I hate it.
40680Sstevel@tonic-gateif ($^W) {
40690Sstevel@tonic-gate    $CGI::CGI = '';
40700Sstevel@tonic-gate    $CGI::CGI=<<EOF;
40710Sstevel@tonic-gate    $CGI::VERSION;
40720Sstevel@tonic-gate    $MultipartBuffer::SPIN_LOOP_MAX;
40730Sstevel@tonic-gate    $MultipartBuffer::CRLF;
40740Sstevel@tonic-gate    $MultipartBuffer::TIMEOUT;
40750Sstevel@tonic-gate    $MultipartBuffer::INITIAL_FILLUNIT;
40760Sstevel@tonic-gateEOF
40770Sstevel@tonic-gate    ;
40780Sstevel@tonic-gate}
40790Sstevel@tonic-gate
40800Sstevel@tonic-gate1;
40810Sstevel@tonic-gate
40820Sstevel@tonic-gate__END__
40830Sstevel@tonic-gate
40840Sstevel@tonic-gate=head1 NAME
40850Sstevel@tonic-gate
40860Sstevel@tonic-gateCGI - Simple Common Gateway Interface Class
40870Sstevel@tonic-gate
40880Sstevel@tonic-gate=head1 SYNOPSIS
40890Sstevel@tonic-gate
40900Sstevel@tonic-gate  # CGI script that creates a fill-out form
40910Sstevel@tonic-gate  # and echoes back its values.
40920Sstevel@tonic-gate
40930Sstevel@tonic-gate  use CGI qw/:standard/;
40940Sstevel@tonic-gate  print header,
40950Sstevel@tonic-gate        start_html('A Simple Example'),
40960Sstevel@tonic-gate        h1('A Simple Example'),
40970Sstevel@tonic-gate        start_form,
40980Sstevel@tonic-gate        "What's your name? ",textfield('name'),p,
40990Sstevel@tonic-gate        "What's the combination?", p,
41000Sstevel@tonic-gate        checkbox_group(-name=>'words',
41010Sstevel@tonic-gate		       -values=>['eenie','meenie','minie','moe'],
41020Sstevel@tonic-gate		       -defaults=>['eenie','minie']), p,
41030Sstevel@tonic-gate        "What's your favorite color? ",
41040Sstevel@tonic-gate        popup_menu(-name=>'color',
41050Sstevel@tonic-gate	           -values=>['red','green','blue','chartreuse']),p,
41060Sstevel@tonic-gate        submit,
41070Sstevel@tonic-gate        end_form,
41080Sstevel@tonic-gate        hr;
41090Sstevel@tonic-gate
41100Sstevel@tonic-gate   if (param()) {
4111667Sps156622       my $name      = param('name');
4112667Sps156622       my $keywords  = join ', ',param('words');
4113667Sps156622       my $color     = param('color');
4114667Sps156622       print "Your name is",em(escapeHTML($name)),p,
4115667Sps156622	     "The keywords are: ",em(escapeHTML($keywords)),p,
4116667Sps156622	     "Your favorite color is ",em(escapeHTML($color)),
41170Sstevel@tonic-gate	     hr;
41180Sstevel@tonic-gate   }
41190Sstevel@tonic-gate
41200Sstevel@tonic-gate=head1 ABSTRACT
41210Sstevel@tonic-gate
41220Sstevel@tonic-gateThis perl library uses perl5 objects to make it easy to create Web
41230Sstevel@tonic-gatefill-out forms and parse their contents.  This package defines CGI
41240Sstevel@tonic-gateobjects, entities that contain the values of the current query string
41250Sstevel@tonic-gateand other state variables.  Using a CGI object's methods, you can
41260Sstevel@tonic-gateexamine keywords and parameters passed to your script, and create
41270Sstevel@tonic-gateforms whose initial values are taken from the current query (thereby
41280Sstevel@tonic-gatepreserving state information).  The module provides shortcut functions
41290Sstevel@tonic-gatethat produce boilerplate HTML, reducing typing and coding errors. It
41300Sstevel@tonic-gatealso provides functionality for some of the more advanced features of
41310Sstevel@tonic-gateCGI scripting, including support for file uploads, cookies, cascading
41320Sstevel@tonic-gatestyle sheets, server push, and frames.
41330Sstevel@tonic-gate
41340Sstevel@tonic-gateCGI.pm also provides a simple function-oriented programming style for
41350Sstevel@tonic-gatethose who don't need its object-oriented features.
41360Sstevel@tonic-gate
41370Sstevel@tonic-gateThe current version of CGI.pm is available at
41380Sstevel@tonic-gate
41390Sstevel@tonic-gate  http://www.genome.wi.mit.edu/ftp/pub/software/WWW/cgi_docs.html
41400Sstevel@tonic-gate  ftp://ftp-genome.wi.mit.edu/pub/software/WWW/
41410Sstevel@tonic-gate
41420Sstevel@tonic-gate=head1 DESCRIPTION
41430Sstevel@tonic-gate
41440Sstevel@tonic-gate=head2 PROGRAMMING STYLE
41450Sstevel@tonic-gate
41460Sstevel@tonic-gateThere are two styles of programming with CGI.pm, an object-oriented
41470Sstevel@tonic-gatestyle and a function-oriented style.  In the object-oriented style you
41480Sstevel@tonic-gatecreate one or more CGI objects and then use object methods to create
41490Sstevel@tonic-gatethe various elements of the page.  Each CGI object starts out with the
41500Sstevel@tonic-gatelist of named parameters that were passed to your CGI script by the
41510Sstevel@tonic-gateserver.  You can modify the objects, save them to a file or database
41520Sstevel@tonic-gateand recreate them.  Because each object corresponds to the "state" of
41530Sstevel@tonic-gatethe CGI script, and because each object's parameter list is
41540Sstevel@tonic-gateindependent of the others, this allows you to save the state of the
41550Sstevel@tonic-gatescript and restore it later.
41560Sstevel@tonic-gate
41570Sstevel@tonic-gateFor example, using the object oriented style, here is how you create
41580Sstevel@tonic-gatea simple "Hello World" HTML page:
41590Sstevel@tonic-gate
41600Sstevel@tonic-gate   #!/usr/local/bin/perl -w
41610Sstevel@tonic-gate   use CGI;                             # load CGI routines
41620Sstevel@tonic-gate   $q = new CGI;                        # create new CGI object
41630Sstevel@tonic-gate   print $q->header,                    # create the HTTP header
41640Sstevel@tonic-gate         $q->start_html('hello world'), # start the HTML
41650Sstevel@tonic-gate         $q->h1('hello world'),         # level 1 header
41660Sstevel@tonic-gate         $q->end_html;                  # end the HTML
41670Sstevel@tonic-gate
41680Sstevel@tonic-gateIn the function-oriented style, there is one default CGI object that
41690Sstevel@tonic-gateyou rarely deal with directly.  Instead you just call functions to
41700Sstevel@tonic-gateretrieve CGI parameters, create HTML tags, manage cookies, and so
41710Sstevel@tonic-gateon.  This provides you with a cleaner programming interface, but
41720Sstevel@tonic-gatelimits you to using one CGI object at a time.  The following example
41730Sstevel@tonic-gateprints the same page, but uses the function-oriented interface.
41740Sstevel@tonic-gateThe main differences are that we now need to import a set of functions
41750Sstevel@tonic-gateinto our name space (usually the "standard" functions), and we don't
41760Sstevel@tonic-gateneed to create the CGI object.
41770Sstevel@tonic-gate
41780Sstevel@tonic-gate   #!/usr/local/bin/perl
41790Sstevel@tonic-gate   use CGI qw/:standard/;           # load standard CGI routines
41800Sstevel@tonic-gate   print header,                    # create the HTTP header
41810Sstevel@tonic-gate         start_html('hello world'), # start the HTML
41820Sstevel@tonic-gate         h1('hello world'),         # level 1 header
41830Sstevel@tonic-gate         end_html;                  # end the HTML
41840Sstevel@tonic-gate
41850Sstevel@tonic-gateThe examples in this document mainly use the object-oriented style.
41860Sstevel@tonic-gateSee HOW TO IMPORT FUNCTIONS for important information on
41870Sstevel@tonic-gatefunction-oriented programming in CGI.pm
41880Sstevel@tonic-gate
41890Sstevel@tonic-gate=head2 CALLING CGI.PM ROUTINES
41900Sstevel@tonic-gate
41910Sstevel@tonic-gateMost CGI.pm routines accept several arguments, sometimes as many as 20
41920Sstevel@tonic-gateoptional ones!  To simplify this interface, all routines use a named
41930Sstevel@tonic-gateargument calling style that looks like this:
41940Sstevel@tonic-gate
41950Sstevel@tonic-gate   print $q->header(-type=>'image/gif',-expires=>'+3d');
41960Sstevel@tonic-gate
41970Sstevel@tonic-gateEach argument name is preceded by a dash.  Neither case nor order
41980Sstevel@tonic-gatematters in the argument list.  -type, -Type, and -TYPE are all
41990Sstevel@tonic-gateacceptable.  In fact, only the first argument needs to begin with a
42000Sstevel@tonic-gatedash.  If a dash is present in the first argument, CGI.pm assumes
42010Sstevel@tonic-gatedashes for the subsequent ones.
42020Sstevel@tonic-gate
42030Sstevel@tonic-gateSeveral routines are commonly called with just one argument.  In the
42040Sstevel@tonic-gatecase of these routines you can provide the single argument without an
42050Sstevel@tonic-gateargument name.  header() happens to be one of these routines.  In this
42060Sstevel@tonic-gatecase, the single argument is the document type.
42070Sstevel@tonic-gate
42080Sstevel@tonic-gate   print $q->header('text/html');
42090Sstevel@tonic-gate
42100Sstevel@tonic-gateOther such routines are documented below.
42110Sstevel@tonic-gate
42120Sstevel@tonic-gateSometimes named arguments expect a scalar, sometimes a reference to an
42130Sstevel@tonic-gatearray, and sometimes a reference to a hash.  Often, you can pass any
42140Sstevel@tonic-gatetype of argument and the routine will do whatever is most appropriate.
42150Sstevel@tonic-gateFor example, the param() routine is used to set a CGI parameter to a
42160Sstevel@tonic-gatesingle or a multi-valued value.  The two cases are shown below:
42170Sstevel@tonic-gate
42180Sstevel@tonic-gate   $q->param(-name=>'veggie',-value=>'tomato');
42190Sstevel@tonic-gate   $q->param(-name=>'veggie',-value=>['tomato','tomahto','potato','potahto']);
42200Sstevel@tonic-gate
42210Sstevel@tonic-gateA large number of routines in CGI.pm actually aren't specifically
42220Sstevel@tonic-gatedefined in the module, but are generated automatically as needed.
42230Sstevel@tonic-gateThese are the "HTML shortcuts," routines that generate HTML tags for
42240Sstevel@tonic-gateuse in dynamically-generated pages.  HTML tags have both attributes
42250Sstevel@tonic-gate(the attribute="value" pairs within the tag itself) and contents (the
42260Sstevel@tonic-gatepart between the opening and closing pairs.)  To distinguish between
42270Sstevel@tonic-gateattributes and contents, CGI.pm uses the convention of passing HTML
42280Sstevel@tonic-gateattributes as a hash reference as the first argument, and the
42290Sstevel@tonic-gatecontents, if any, as any subsequent arguments.  It works out like
42300Sstevel@tonic-gatethis:
42310Sstevel@tonic-gate
42320Sstevel@tonic-gate   Code                           Generated HTML
42330Sstevel@tonic-gate   ----                           --------------
42340Sstevel@tonic-gate   h1()                           <h1>
42350Sstevel@tonic-gate   h1('some','contents');         <h1>some contents</h1>
42360Sstevel@tonic-gate   h1({-align=>left});            <h1 align="LEFT">
42370Sstevel@tonic-gate   h1({-align=>left},'contents'); <h1 align="LEFT">contents</h1>
42380Sstevel@tonic-gate
42390Sstevel@tonic-gateHTML tags are described in more detail later.
42400Sstevel@tonic-gate
42410Sstevel@tonic-gateMany newcomers to CGI.pm are puzzled by the difference between the
42420Sstevel@tonic-gatecalling conventions for the HTML shortcuts, which require curly braces
42430Sstevel@tonic-gatearound the HTML tag attributes, and the calling conventions for other
42440Sstevel@tonic-gateroutines, which manage to generate attributes without the curly
42450Sstevel@tonic-gatebrackets.  Don't be confused.  As a convenience the curly braces are
42460Sstevel@tonic-gateoptional in all but the HTML shortcuts.  If you like, you can use
42470Sstevel@tonic-gatecurly braces when calling any routine that takes named arguments.  For
42480Sstevel@tonic-gateexample:
42490Sstevel@tonic-gate
42500Sstevel@tonic-gate   print $q->header( {-type=>'image/gif',-expires=>'+3d'} );
42510Sstevel@tonic-gate
42520Sstevel@tonic-gateIf you use the B<-w> switch, you will be warned that some CGI.pm argument
42530Sstevel@tonic-gatenames conflict with built-in Perl functions.  The most frequent of
42540Sstevel@tonic-gatethese is the -values argument, used to create multi-valued menus,
42550Sstevel@tonic-gateradio button clusters and the like.  To get around this warning, you
42560Sstevel@tonic-gatehave several choices:
42570Sstevel@tonic-gate
42580Sstevel@tonic-gate=over 4
42590Sstevel@tonic-gate
42600Sstevel@tonic-gate=item 1.
42610Sstevel@tonic-gate
42620Sstevel@tonic-gateUse another name for the argument, if one is available.
42630Sstevel@tonic-gateFor example, -value is an alias for -values.
42640Sstevel@tonic-gate
42650Sstevel@tonic-gate=item 2.
42660Sstevel@tonic-gate
42670Sstevel@tonic-gateChange the capitalization, e.g. -Values
42680Sstevel@tonic-gate
42690Sstevel@tonic-gate=item 3.
42700Sstevel@tonic-gate
42710Sstevel@tonic-gatePut quotes around the argument name, e.g. '-values'
42720Sstevel@tonic-gate
42730Sstevel@tonic-gate=back
42740Sstevel@tonic-gate
42750Sstevel@tonic-gateMany routines will do something useful with a named argument that it
42760Sstevel@tonic-gatedoesn't recognize.  For example, you can produce non-standard HTTP
42770Sstevel@tonic-gateheader fields by providing them as named arguments:
42780Sstevel@tonic-gate
42790Sstevel@tonic-gate  print $q->header(-type  =>  'text/html',
42800Sstevel@tonic-gate                   -cost  =>  'Three smackers',
42810Sstevel@tonic-gate                   -annoyance_level => 'high',
42820Sstevel@tonic-gate                   -complaints_to   => 'bit bucket');
42830Sstevel@tonic-gate
42840Sstevel@tonic-gateThis will produce the following nonstandard HTTP header:
42850Sstevel@tonic-gate
42860Sstevel@tonic-gate   HTTP/1.0 200 OK
42870Sstevel@tonic-gate   Cost: Three smackers
42880Sstevel@tonic-gate   Annoyance-level: high
42890Sstevel@tonic-gate   Complaints-to: bit bucket
42900Sstevel@tonic-gate   Content-type: text/html
42910Sstevel@tonic-gate
42920Sstevel@tonic-gateNotice the way that underscores are translated automatically into
42930Sstevel@tonic-gatehyphens.  HTML-generating routines perform a different type of
42940Sstevel@tonic-gatetranslation.
42950Sstevel@tonic-gate
42960Sstevel@tonic-gateThis feature allows you to keep up with the rapidly changing HTTP and
42970Sstevel@tonic-gateHTML "standards".
42980Sstevel@tonic-gate
42990Sstevel@tonic-gate=head2 CREATING A NEW QUERY OBJECT (OBJECT-ORIENTED STYLE):
43000Sstevel@tonic-gate
43010Sstevel@tonic-gate     $query = new CGI;
43020Sstevel@tonic-gate
43030Sstevel@tonic-gateThis will parse the input (from both POST and GET methods) and store
4304*6287Sps156622it into a perl5 object called $query.
4305*6287Sps156622
4306*6287Sps156622Any filehandles from file uploads will have their position reset to
4307*6287Sps156622the beginning of the file.
43080Sstevel@tonic-gate
43090Sstevel@tonic-gate=head2 CREATING A NEW QUERY OBJECT FROM AN INPUT FILE
43100Sstevel@tonic-gate
43110Sstevel@tonic-gate     $query = new CGI(INPUTFILE);
43120Sstevel@tonic-gate
43130Sstevel@tonic-gateIf you provide a file handle to the new() method, it will read
43140Sstevel@tonic-gateparameters from the file (or STDIN, or whatever).  The file can be in
43150Sstevel@tonic-gateany of the forms describing below under debugging (i.e. a series of
43160Sstevel@tonic-gatenewline delimited TAG=VALUE pairs will work).  Conveniently, this type
43170Sstevel@tonic-gateof file is created by the save() method (see below).  Multiple records
43180Sstevel@tonic-gatecan be saved and restored.
43190Sstevel@tonic-gate
43200Sstevel@tonic-gatePerl purists will be pleased to know that this syntax accepts
43210Sstevel@tonic-gatereferences to file handles, or even references to filehandle globs,
43220Sstevel@tonic-gatewhich is the "official" way to pass a filehandle:
43230Sstevel@tonic-gate
43240Sstevel@tonic-gate    $query = new CGI(\*STDIN);
43250Sstevel@tonic-gate
43260Sstevel@tonic-gateYou can also initialize the CGI object with a FileHandle or IO::File
43270Sstevel@tonic-gateobject.
43280Sstevel@tonic-gate
43290Sstevel@tonic-gateIf you are using the function-oriented interface and want to
43300Sstevel@tonic-gateinitialize CGI state from a file handle, the way to do this is with
43310Sstevel@tonic-gateB<restore_parameters()>.  This will (re)initialize the
43320Sstevel@tonic-gatedefault CGI object from the indicated file handle.
43330Sstevel@tonic-gate
43340Sstevel@tonic-gate    open (IN,"test.in") || die;
43350Sstevel@tonic-gate    restore_parameters(IN);
43360Sstevel@tonic-gate    close IN;
43370Sstevel@tonic-gate
43380Sstevel@tonic-gateYou can also initialize the query object from an associative array
43390Sstevel@tonic-gatereference:
43400Sstevel@tonic-gate
43410Sstevel@tonic-gate    $query = new CGI( {'dinosaur'=>'barney',
43420Sstevel@tonic-gate		       'song'=>'I love you',
43430Sstevel@tonic-gate		       'friends'=>[qw/Jessica George Nancy/]}
43440Sstevel@tonic-gate		    );
43450Sstevel@tonic-gate
43460Sstevel@tonic-gateor from a properly formatted, URL-escaped query string:
43470Sstevel@tonic-gate
43480Sstevel@tonic-gate    $query = new CGI('dinosaur=barney&color=purple');
43490Sstevel@tonic-gate
43500Sstevel@tonic-gateor from a previously existing CGI object (currently this clones the
43510Sstevel@tonic-gateparameter list, but none of the other object-specific fields, such as
43520Sstevel@tonic-gateautoescaping):
43530Sstevel@tonic-gate
43540Sstevel@tonic-gate    $old_query = new CGI;
43550Sstevel@tonic-gate    $new_query = new CGI($old_query);
43560Sstevel@tonic-gate
43570Sstevel@tonic-gateTo create an empty query, initialize it from an empty string or hash:
43580Sstevel@tonic-gate
43590Sstevel@tonic-gate   $empty_query = new CGI("");
43600Sstevel@tonic-gate
43610Sstevel@tonic-gate       -or-
43620Sstevel@tonic-gate
43630Sstevel@tonic-gate   $empty_query = new CGI({});
43640Sstevel@tonic-gate
43650Sstevel@tonic-gate=head2 FETCHING A LIST OF KEYWORDS FROM THE QUERY:
43660Sstevel@tonic-gate
43670Sstevel@tonic-gate     @keywords = $query->keywords
43680Sstevel@tonic-gate
43690Sstevel@tonic-gateIf the script was invoked as the result of an <ISINDEX> search, the
43700Sstevel@tonic-gateparsed keywords can be obtained as an array using the keywords() method.
43710Sstevel@tonic-gate
43720Sstevel@tonic-gate=head2 FETCHING THE NAMES OF ALL THE PARAMETERS PASSED TO YOUR SCRIPT:
43730Sstevel@tonic-gate
43740Sstevel@tonic-gate     @names = $query->param
43750Sstevel@tonic-gate
43760Sstevel@tonic-gateIf the script was invoked with a parameter list
43770Sstevel@tonic-gate(e.g. "name1=value1&name2=value2&name3=value3"), the param() method
43780Sstevel@tonic-gatewill return the parameter names as a list.  If the script was invoked
43790Sstevel@tonic-gateas an <ISINDEX> script and contains a string without ampersands
43800Sstevel@tonic-gate(e.g. "value1+value2+value3") , there will be a single parameter named
43810Sstevel@tonic-gate"keywords" containing the "+"-delimited keywords.
43820Sstevel@tonic-gate
43830Sstevel@tonic-gateNOTE: As of version 1.5, the array of parameter names returned will
43840Sstevel@tonic-gatebe in the same order as they were submitted by the browser.
43850Sstevel@tonic-gateUsually this order is the same as the order in which the
43860Sstevel@tonic-gateparameters are defined in the form (however, this isn't part
43870Sstevel@tonic-gateof the spec, and so isn't guaranteed).
43880Sstevel@tonic-gate
43890Sstevel@tonic-gate=head2 FETCHING THE VALUE OR VALUES OF A SINGLE NAMED PARAMETER:
43900Sstevel@tonic-gate
43910Sstevel@tonic-gate    @values = $query->param('foo');
43920Sstevel@tonic-gate
43930Sstevel@tonic-gate	      -or-
43940Sstevel@tonic-gate
43950Sstevel@tonic-gate    $value = $query->param('foo');
43960Sstevel@tonic-gate
43970Sstevel@tonic-gatePass the param() method a single argument to fetch the value of the
43980Sstevel@tonic-gatenamed parameter. If the parameter is multivalued (e.g. from multiple
43990Sstevel@tonic-gateselections in a scrolling list), you can ask to receive an array.  Otherwise
44000Sstevel@tonic-gatethe method will return a single value.
44010Sstevel@tonic-gate
44020Sstevel@tonic-gateIf a value is not given in the query string, as in the queries
44030Sstevel@tonic-gate"name1=&name2=" or "name1&name2", it will be returned as an empty
44040Sstevel@tonic-gatestring.  This feature is new in 2.63.
44050Sstevel@tonic-gate
44060Sstevel@tonic-gate
44070Sstevel@tonic-gateIf the parameter does not exist at all, then param() will return undef
44080Sstevel@tonic-gatein a scalar context, and the empty list in a list context.
44090Sstevel@tonic-gate
44100Sstevel@tonic-gate
44110Sstevel@tonic-gate=head2 SETTING THE VALUE(S) OF A NAMED PARAMETER:
44120Sstevel@tonic-gate
44130Sstevel@tonic-gate    $query->param('foo','an','array','of','values');
44140Sstevel@tonic-gate
44150Sstevel@tonic-gateThis sets the value for the named parameter 'foo' to an array of
44160Sstevel@tonic-gatevalues.  This is one way to change the value of a field AFTER
44170Sstevel@tonic-gatethe script has been invoked once before.  (Another way is with
44180Sstevel@tonic-gatethe -override parameter accepted by all methods that generate
44190Sstevel@tonic-gateform elements.)
44200Sstevel@tonic-gate
44210Sstevel@tonic-gateparam() also recognizes a named parameter style of calling described
44220Sstevel@tonic-gatein more detail later:
44230Sstevel@tonic-gate
44240Sstevel@tonic-gate    $query->param(-name=>'foo',-values=>['an','array','of','values']);
44250Sstevel@tonic-gate
44260Sstevel@tonic-gate			      -or-
44270Sstevel@tonic-gate
44280Sstevel@tonic-gate    $query->param(-name=>'foo',-value=>'the value');
44290Sstevel@tonic-gate
44300Sstevel@tonic-gate=head2 APPENDING ADDITIONAL VALUES TO A NAMED PARAMETER:
44310Sstevel@tonic-gate
44320Sstevel@tonic-gate   $query->append(-name=>'foo',-values=>['yet','more','values']);
44330Sstevel@tonic-gate
44340Sstevel@tonic-gateThis adds a value or list of values to the named parameter.  The
44350Sstevel@tonic-gatevalues are appended to the end of the parameter if it already exists.
44360Sstevel@tonic-gateOtherwise the parameter is created.  Note that this method only
44370Sstevel@tonic-gaterecognizes the named argument calling syntax.
44380Sstevel@tonic-gate
44390Sstevel@tonic-gate=head2 IMPORTING ALL PARAMETERS INTO A NAMESPACE:
44400Sstevel@tonic-gate
44410Sstevel@tonic-gate   $query->import_names('R');
44420Sstevel@tonic-gate
44430Sstevel@tonic-gateThis creates a series of variables in the 'R' namespace.  For example,
44440Sstevel@tonic-gate$R::foo, @R:foo.  For keyword lists, a variable @R::keywords will appear.
44450Sstevel@tonic-gateIf no namespace is given, this method will assume 'Q'.
44460Sstevel@tonic-gateWARNING:  don't import anything into 'main'; this is a major security
44470Sstevel@tonic-gaterisk!!!!
44480Sstevel@tonic-gate
44490Sstevel@tonic-gateNOTE 1: Variable names are transformed as necessary into legal Perl
44500Sstevel@tonic-gatevariable names.  All non-legal characters are transformed into
44510Sstevel@tonic-gateunderscores.  If you need to keep the original names, you should use
44520Sstevel@tonic-gatethe param() method instead to access CGI variables by name.
44530Sstevel@tonic-gate
44540Sstevel@tonic-gateNOTE 2: In older versions, this method was called B<import()>.  As of version 2.20,
44550Sstevel@tonic-gatethis name has been removed completely to avoid conflict with the built-in
44560Sstevel@tonic-gatePerl module B<import> operator.
44570Sstevel@tonic-gate
44580Sstevel@tonic-gate=head2 DELETING A PARAMETER COMPLETELY:
44590Sstevel@tonic-gate
44600Sstevel@tonic-gate    $query->delete('foo','bar','baz');
44610Sstevel@tonic-gate
44620Sstevel@tonic-gateThis completely clears a list of parameters.  It sometimes useful for
44630Sstevel@tonic-gateresetting parameters that you don't want passed down between script
44640Sstevel@tonic-gateinvocations.
44650Sstevel@tonic-gate
44660Sstevel@tonic-gateIf you are using the function call interface, use "Delete()" instead
44670Sstevel@tonic-gateto avoid conflicts with Perl's built-in delete operator.
44680Sstevel@tonic-gate
44690Sstevel@tonic-gate=head2 DELETING ALL PARAMETERS:
44700Sstevel@tonic-gate
44710Sstevel@tonic-gate   $query->delete_all();
44720Sstevel@tonic-gate
44730Sstevel@tonic-gateThis clears the CGI object completely.  It might be useful to ensure
44740Sstevel@tonic-gatethat all the defaults are taken when you create a fill-out form.
44750Sstevel@tonic-gate
44760Sstevel@tonic-gateUse Delete_all() instead if you are using the function call interface.
44770Sstevel@tonic-gate
4478*6287Sps156622=head2 HANDLING NON-URLENCODED ARGUMENTS
4479*6287Sps156622
4480*6287Sps156622
4481*6287Sps156622If POSTed data is not of type application/x-www-form-urlencoded or
4482*6287Sps156622multipart/form-data, then the POSTed data will not be processed, but
4483*6287Sps156622instead be returned as-is in a parameter named POSTDATA.  To retrieve
4484*6287Sps156622it, use code like this:
4485*6287Sps156622
4486*6287Sps156622   my $data = $query->param('POSTDATA');
4487*6287Sps156622
4488*6287Sps156622Likewise if PUTed data can be retrieved with code like this:
4489*6287Sps156622
4490*6287Sps156622   my $data = $query->param('PUTDATA');
4491*6287Sps156622
4492*6287Sps156622(If you don't know what the preceding means, don't worry about it.  It
4493*6287Sps156622only affects people trying to use CGI for XML processing and other
4494*6287Sps156622specialized tasks.)
4495*6287Sps156622
4496*6287Sps156622
44970Sstevel@tonic-gate=head2 DIRECT ACCESS TO THE PARAMETER LIST:
44980Sstevel@tonic-gate
44990Sstevel@tonic-gate   $q->param_fetch('address')->[1] = '1313 Mockingbird Lane';
45000Sstevel@tonic-gate   unshift @{$q->param_fetch(-name=>'address')},'George Munster';
45010Sstevel@tonic-gate
45020Sstevel@tonic-gateIf you need access to the parameter list in a way that isn't covered
45030Sstevel@tonic-gateby the methods above, you can obtain a direct reference to it by
45040Sstevel@tonic-gatecalling the B<param_fetch()> method with the name of the .  This
45050Sstevel@tonic-gatewill return an array reference to the named parameters, which you then
45060Sstevel@tonic-gatecan manipulate in any way you like.
45070Sstevel@tonic-gate
45080Sstevel@tonic-gateYou can also use a named argument style using the B<-name> argument.
45090Sstevel@tonic-gate
45100Sstevel@tonic-gate=head2 FETCHING THE PARAMETER LIST AS A HASH:
45110Sstevel@tonic-gate
45120Sstevel@tonic-gate    $params = $q->Vars;
45130Sstevel@tonic-gate    print $params->{'address'};
45140Sstevel@tonic-gate    @foo = split("\0",$params->{'foo'});
45150Sstevel@tonic-gate    %params = $q->Vars;
45160Sstevel@tonic-gate
45170Sstevel@tonic-gate    use CGI ':cgi-lib';
45180Sstevel@tonic-gate    $params = Vars;
45190Sstevel@tonic-gate
45200Sstevel@tonic-gateMany people want to fetch the entire parameter list as a hash in which
45210Sstevel@tonic-gatethe keys are the names of the CGI parameters, and the values are the
45220Sstevel@tonic-gateparameters' values.  The Vars() method does this.  Called in a scalar
45230Sstevel@tonic-gatecontext, it returns the parameter list as a tied hash reference.
45240Sstevel@tonic-gateChanging a key changes the value of the parameter in the underlying
45250Sstevel@tonic-gateCGI parameter list.  Called in a list context, it returns the
45260Sstevel@tonic-gateparameter list as an ordinary hash.  This allows you to read the
45270Sstevel@tonic-gatecontents of the parameter list, but not to change it.
45280Sstevel@tonic-gate
45290Sstevel@tonic-gateWhen using this, the thing you must watch out for are multivalued CGI
45300Sstevel@tonic-gateparameters.  Because a hash cannot distinguish between scalar and
45310Sstevel@tonic-gatelist context, multivalued parameters will be returned as a packed
45320Sstevel@tonic-gatestring, separated by the "\0" (null) character.  You must split this
45330Sstevel@tonic-gatepacked string in order to get at the individual values.  This is the
45340Sstevel@tonic-gateconvention introduced long ago by Steve Brenner in his cgi-lib.pl
45350Sstevel@tonic-gatemodule for Perl version 4.
45360Sstevel@tonic-gate
45370Sstevel@tonic-gateIf you wish to use Vars() as a function, import the I<:cgi-lib> set of
45380Sstevel@tonic-gatefunction calls (also see the section on CGI-LIB compatibility).
45390Sstevel@tonic-gate
45400Sstevel@tonic-gate=head2 SAVING THE STATE OF THE SCRIPT TO A FILE:
45410Sstevel@tonic-gate
4542667Sps156622    $query->save(\*FILEHANDLE)
45430Sstevel@tonic-gate
45440Sstevel@tonic-gateThis will write the current state of the form to the provided
45450Sstevel@tonic-gatefilehandle.  You can read it back in by providing a filehandle
45460Sstevel@tonic-gateto the new() method.  Note that the filehandle can be a file, a pipe,
45470Sstevel@tonic-gateor whatever!
45480Sstevel@tonic-gate
45490Sstevel@tonic-gateThe format of the saved file is:
45500Sstevel@tonic-gate
45510Sstevel@tonic-gate	NAME1=VALUE1
45520Sstevel@tonic-gate	NAME1=VALUE1'
45530Sstevel@tonic-gate	NAME2=VALUE2
45540Sstevel@tonic-gate	NAME3=VALUE3
45550Sstevel@tonic-gate	=
45560Sstevel@tonic-gate
45570Sstevel@tonic-gateBoth name and value are URL escaped.  Multi-valued CGI parameters are
45580Sstevel@tonic-gaterepresented as repeated names.  A session record is delimited by a
45590Sstevel@tonic-gatesingle = symbol.  You can write out multiple records and read them
45600Sstevel@tonic-gateback in with several calls to B<new>.  You can do this across several
45610Sstevel@tonic-gatesessions by opening the file in append mode, allowing you to create
45620Sstevel@tonic-gateprimitive guest books, or to keep a history of users' queries.  Here's
45630Sstevel@tonic-gatea short example of creating multiple session records:
45640Sstevel@tonic-gate
45650Sstevel@tonic-gate   use CGI;
45660Sstevel@tonic-gate
45670Sstevel@tonic-gate   open (OUT,">>test.out") || die;
45680Sstevel@tonic-gate   $records = 5;
45690Sstevel@tonic-gate   foreach (0..$records) {
45700Sstevel@tonic-gate       my $q = new CGI;
45710Sstevel@tonic-gate       $q->param(-name=>'counter',-value=>$_);
4572667Sps156622       $q->save(\*OUT);
45730Sstevel@tonic-gate   }
45740Sstevel@tonic-gate   close OUT;
45750Sstevel@tonic-gate
45760Sstevel@tonic-gate   # reopen for reading
45770Sstevel@tonic-gate   open (IN,"test.out") || die;
45780Sstevel@tonic-gate   while (!eof(IN)) {
4579667Sps156622       my $q = new CGI(\*IN);
45800Sstevel@tonic-gate       print $q->param('counter'),"\n";
45810Sstevel@tonic-gate   }
45820Sstevel@tonic-gate
45830Sstevel@tonic-gateThe file format used for save/restore is identical to that used by the
45840Sstevel@tonic-gateWhitehead Genome Center's data exchange format "Boulderio", and can be
45850Sstevel@tonic-gatemanipulated and even databased using Boulderio utilities.  See
45860Sstevel@tonic-gate
45870Sstevel@tonic-gate  http://stein.cshl.org/boulder/
45880Sstevel@tonic-gate
45890Sstevel@tonic-gatefor further details.
45900Sstevel@tonic-gate
45910Sstevel@tonic-gateIf you wish to use this method from the function-oriented (non-OO)
45920Sstevel@tonic-gateinterface, the exported name for this method is B<save_parameters()>.
45930Sstevel@tonic-gate
45940Sstevel@tonic-gate=head2 RETRIEVING CGI ERRORS
45950Sstevel@tonic-gate
45960Sstevel@tonic-gateErrors can occur while processing user input, particularly when
45970Sstevel@tonic-gateprocessing uploaded files.  When these errors occur, CGI will stop
45980Sstevel@tonic-gateprocessing and return an empty parameter list.  You can test for
45990Sstevel@tonic-gatethe existence and nature of errors using the I<cgi_error()> function.
46000Sstevel@tonic-gateThe error messages are formatted as HTTP status codes. You can either
46010Sstevel@tonic-gateincorporate the error text into an HTML page, or use it as the value
46020Sstevel@tonic-gateof the HTTP status:
46030Sstevel@tonic-gate
46040Sstevel@tonic-gate    my $error = $q->cgi_error;
46050Sstevel@tonic-gate    if ($error) {
46060Sstevel@tonic-gate	print $q->header(-status=>$error),
46070Sstevel@tonic-gate	      $q->start_html('Problems'),
46080Sstevel@tonic-gate              $q->h2('Request not processed'),
46090Sstevel@tonic-gate	      $q->strong($error);
46100Sstevel@tonic-gate        exit 0;
46110Sstevel@tonic-gate    }
46120Sstevel@tonic-gate
46130Sstevel@tonic-gateWhen using the function-oriented interface (see the next section),
46140Sstevel@tonic-gateerrors may only occur the first time you call I<param()>. Be ready
46150Sstevel@tonic-gatefor this!
46160Sstevel@tonic-gate
46170Sstevel@tonic-gate=head2 USING THE FUNCTION-ORIENTED INTERFACE
46180Sstevel@tonic-gate
46190Sstevel@tonic-gateTo use the function-oriented interface, you must specify which CGI.pm
46200Sstevel@tonic-gateroutines or sets of routines to import into your script's namespace.
46210Sstevel@tonic-gateThere is a small overhead associated with this importation, but it
46220Sstevel@tonic-gateisn't much.
46230Sstevel@tonic-gate
46240Sstevel@tonic-gate   use CGI <list of methods>;
46250Sstevel@tonic-gate
46260Sstevel@tonic-gateThe listed methods will be imported into the current package; you can
46270Sstevel@tonic-gatecall them directly without creating a CGI object first.  This example
46280Sstevel@tonic-gateshows how to import the B<param()> and B<header()>
46290Sstevel@tonic-gatemethods, and then use them directly:
46300Sstevel@tonic-gate
46310Sstevel@tonic-gate   use CGI 'param','header';
46320Sstevel@tonic-gate   print header('text/plain');
46330Sstevel@tonic-gate   $zipcode = param('zipcode');
46340Sstevel@tonic-gate
46350Sstevel@tonic-gateMore frequently, you'll import common sets of functions by referring
46360Sstevel@tonic-gateto the groups by name.  All function sets are preceded with a ":"
46370Sstevel@tonic-gatecharacter as in ":html3" (for tags defined in the HTML 3 standard).
46380Sstevel@tonic-gate
46390Sstevel@tonic-gateHere is a list of the function sets you can import:
46400Sstevel@tonic-gate
46410Sstevel@tonic-gate=over 4
46420Sstevel@tonic-gate
46430Sstevel@tonic-gate=item B<:cgi>
46440Sstevel@tonic-gate
46450Sstevel@tonic-gateImport all CGI-handling methods, such as B<param()>, B<path_info()>
46460Sstevel@tonic-gateand the like.
46470Sstevel@tonic-gate
46480Sstevel@tonic-gate=item B<:form>
46490Sstevel@tonic-gate
46500Sstevel@tonic-gateImport all fill-out form generating methods, such as B<textfield()>.
46510Sstevel@tonic-gate
46520Sstevel@tonic-gate=item B<:html2>
46530Sstevel@tonic-gate
46540Sstevel@tonic-gateImport all methods that generate HTML 2.0 standard elements.
46550Sstevel@tonic-gate
46560Sstevel@tonic-gate=item B<:html3>
46570Sstevel@tonic-gate
46580Sstevel@tonic-gateImport all methods that generate HTML 3.0 elements (such as
46590Sstevel@tonic-gate<table>, <super> and <sub>).
46600Sstevel@tonic-gate
46610Sstevel@tonic-gate=item B<:html4>
46620Sstevel@tonic-gate
46630Sstevel@tonic-gateImport all methods that generate HTML 4 elements (such as
46640Sstevel@tonic-gate<abbrev>, <acronym> and <thead>).
46650Sstevel@tonic-gate
46660Sstevel@tonic-gate=item B<:netscape>
46670Sstevel@tonic-gate
46680Sstevel@tonic-gateImport all methods that generate Netscape-specific HTML extensions.
46690Sstevel@tonic-gate
46700Sstevel@tonic-gate=item B<:html>
46710Sstevel@tonic-gate
46720Sstevel@tonic-gateImport all HTML-generating shortcuts (i.e. 'html2' + 'html3' +
46730Sstevel@tonic-gate'netscape')...
46740Sstevel@tonic-gate
46750Sstevel@tonic-gate=item B<:standard>
46760Sstevel@tonic-gate
46770Sstevel@tonic-gateImport "standard" features, 'html2', 'html3', 'html4', 'form' and 'cgi'.
46780Sstevel@tonic-gate
46790Sstevel@tonic-gate=item B<:all>
46800Sstevel@tonic-gate
46810Sstevel@tonic-gateImport all the available methods.  For the full list, see the CGI.pm
46820Sstevel@tonic-gatecode, where the variable %EXPORT_TAGS is defined.
46830Sstevel@tonic-gate
46840Sstevel@tonic-gate=back
46850Sstevel@tonic-gate
46860Sstevel@tonic-gateIf you import a function name that is not part of CGI.pm, the module
46870Sstevel@tonic-gatewill treat it as a new HTML tag and generate the appropriate
46880Sstevel@tonic-gatesubroutine.  You can then use it like any other HTML tag.  This is to
46890Sstevel@tonic-gateprovide for the rapidly-evolving HTML "standard."  For example, say
46900Sstevel@tonic-gateMicrosoft comes out with a new tag called <gradient> (which causes the
46910Sstevel@tonic-gateuser's desktop to be flooded with a rotating gradient fill until his
46920Sstevel@tonic-gatemachine reboots).  You don't need to wait for a new version of CGI.pm
46930Sstevel@tonic-gateto start using it immediately:
46940Sstevel@tonic-gate
46950Sstevel@tonic-gate   use CGI qw/:standard :html3 gradient/;
46960Sstevel@tonic-gate   print gradient({-start=>'red',-end=>'blue'});
46970Sstevel@tonic-gate
46980Sstevel@tonic-gateNote that in the interests of execution speed CGI.pm does B<not> use
46990Sstevel@tonic-gatethe standard L<Exporter> syntax for specifying load symbols.  This may
47000Sstevel@tonic-gatechange in the future.
47010Sstevel@tonic-gate
47020Sstevel@tonic-gateIf you import any of the state-maintaining CGI or form-generating
47030Sstevel@tonic-gatemethods, a default CGI object will be created and initialized
47040Sstevel@tonic-gateautomatically the first time you use any of the methods that require
47050Sstevel@tonic-gateone to be present.  This includes B<param()>, B<textfield()>,
47060Sstevel@tonic-gateB<submit()> and the like.  (If you need direct access to the CGI
47070Sstevel@tonic-gateobject, you can find it in the global variable B<$CGI::Q>).  By
47080Sstevel@tonic-gateimporting CGI.pm methods, you can create visually elegant scripts:
47090Sstevel@tonic-gate
47100Sstevel@tonic-gate   use CGI qw/:standard/;
47110Sstevel@tonic-gate   print
47120Sstevel@tonic-gate       header,
47130Sstevel@tonic-gate       start_html('Simple Script'),
47140Sstevel@tonic-gate       h1('Simple Script'),
47150Sstevel@tonic-gate       start_form,
47160Sstevel@tonic-gate       "What's your name? ",textfield('name'),p,
47170Sstevel@tonic-gate       "What's the combination?",
47180Sstevel@tonic-gate       checkbox_group(-name=>'words',
47190Sstevel@tonic-gate		      -values=>['eenie','meenie','minie','moe'],
47200Sstevel@tonic-gate		      -defaults=>['eenie','moe']),p,
47210Sstevel@tonic-gate       "What's your favorite color?",
47220Sstevel@tonic-gate       popup_menu(-name=>'color',
47230Sstevel@tonic-gate		  -values=>['red','green','blue','chartreuse']),p,
47240Sstevel@tonic-gate       submit,
47250Sstevel@tonic-gate       end_form,
47260Sstevel@tonic-gate       hr,"\n";
47270Sstevel@tonic-gate
47280Sstevel@tonic-gate    if (param) {
47290Sstevel@tonic-gate       print
47300Sstevel@tonic-gate	   "Your name is ",em(param('name')),p,
47310Sstevel@tonic-gate	   "The keywords are: ",em(join(", ",param('words'))),p,
47320Sstevel@tonic-gate	   "Your favorite color is ",em(param('color')),".\n";
47330Sstevel@tonic-gate    }
47340Sstevel@tonic-gate    print end_html;
47350Sstevel@tonic-gate
47360Sstevel@tonic-gate=head2 PRAGMAS
47370Sstevel@tonic-gate
47380Sstevel@tonic-gateIn addition to the function sets, there are a number of pragmas that
47390Sstevel@tonic-gateyou can import.  Pragmas, which are always preceded by a hyphen,
47400Sstevel@tonic-gatechange the way that CGI.pm functions in various ways.  Pragmas,
47410Sstevel@tonic-gatefunction sets, and individual functions can all be imported in the
47420Sstevel@tonic-gatesame use() line.  For example, the following use statement imports the
47430Sstevel@tonic-gatestandard set of functions and enables debugging mode (pragma
47440Sstevel@tonic-gate-debug):
47450Sstevel@tonic-gate
47460Sstevel@tonic-gate   use CGI qw/:standard -debug/;
47470Sstevel@tonic-gate
47480Sstevel@tonic-gateThe current list of pragmas is as follows:
47490Sstevel@tonic-gate
47500Sstevel@tonic-gate=over 4
47510Sstevel@tonic-gate
47520Sstevel@tonic-gate=item -any
47530Sstevel@tonic-gate
47540Sstevel@tonic-gateWhen you I<use CGI -any>, then any method that the query object
47550Sstevel@tonic-gatedoesn't recognize will be interpreted as a new HTML tag.  This allows
47560Sstevel@tonic-gateyou to support the next I<ad hoc> Netscape or Microsoft HTML
47570Sstevel@tonic-gateextension.  This lets you go wild with new and unsupported tags:
47580Sstevel@tonic-gate
47590Sstevel@tonic-gate   use CGI qw(-any);
47600Sstevel@tonic-gate   $q=new CGI;
47610Sstevel@tonic-gate   print $q->gradient({speed=>'fast',start=>'red',end=>'blue'});
47620Sstevel@tonic-gate
47630Sstevel@tonic-gateSince using <cite>any</cite> causes any mistyped method name
47640Sstevel@tonic-gateto be interpreted as an HTML tag, use it with care or not at
47650Sstevel@tonic-gateall.
47660Sstevel@tonic-gate
47670Sstevel@tonic-gate=item -compile
47680Sstevel@tonic-gate
47690Sstevel@tonic-gateThis causes the indicated autoloaded methods to be compiled up front,
47700Sstevel@tonic-gaterather than deferred to later.  This is useful for scripts that run
47710Sstevel@tonic-gatefor an extended period of time under FastCGI or mod_perl, and for
4772*6287Sps156622those destined to be crunched by Malcolm Beattie's Perl compiler.  Use
47730Sstevel@tonic-gateit in conjunction with the methods or method families you plan to use.
47740Sstevel@tonic-gate
47750Sstevel@tonic-gate   use CGI qw(-compile :standard :html3);
47760Sstevel@tonic-gate
47770Sstevel@tonic-gateor even
47780Sstevel@tonic-gate
47790Sstevel@tonic-gate   use CGI qw(-compile :all);
47800Sstevel@tonic-gate
47810Sstevel@tonic-gateNote that using the -compile pragma in this way will always have
47820Sstevel@tonic-gatethe effect of importing the compiled functions into the current
47830Sstevel@tonic-gatenamespace.  If you want to compile without importing use the
47840Sstevel@tonic-gatecompile() method instead:
47850Sstevel@tonic-gate
47860Sstevel@tonic-gate   use CGI();
47870Sstevel@tonic-gate   CGI->compile();
47880Sstevel@tonic-gate
47890Sstevel@tonic-gateThis is particularly useful in a mod_perl environment, in which you
47900Sstevel@tonic-gatemight want to precompile all CGI routines in a startup script, and
47910Sstevel@tonic-gatethen import the functions individually in each mod_perl script.
47920Sstevel@tonic-gate
47930Sstevel@tonic-gate=item -nosticky
47940Sstevel@tonic-gate
4795667Sps156622By default the CGI module implements a state-preserving behavior
4796667Sps156622called "sticky" fields.  The way this works is that if you are
4797667Sps156622regenerating a form, the methods that generate the form field values
4798667Sps156622will interrogate param() to see if similarly-named parameters are
4799667Sps156622present in the query string. If they find a like-named parameter, they
4800667Sps156622will use it to set their default values.
4801667Sps156622
4802667Sps156622Sometimes this isn't what you want.  The B<-nosticky> pragma prevents
4803667Sps156622this behavior.  You can also selectively change the sticky behavior in
4804667Sps156622each element that you generate.
48050Sstevel@tonic-gate
4806*6287Sps156622=item -tabindex
4807*6287Sps156622
4808*6287Sps156622Automatically add tab index attributes to each form field. With this
4809*6287Sps156622option turned off, you can still add tab indexes manually by passing a
4810*6287Sps156622-tabindex option to each field-generating method.
4811*6287Sps156622
48120Sstevel@tonic-gate=item -no_undef_params
48130Sstevel@tonic-gate
48140Sstevel@tonic-gateThis keeps CGI.pm from including undef params in the parameter list.
48150Sstevel@tonic-gate
48160Sstevel@tonic-gate=item -no_xhtml
48170Sstevel@tonic-gate
48180Sstevel@tonic-gateBy default, CGI.pm versions 2.69 and higher emit XHTML
48190Sstevel@tonic-gate(http://www.w3.org/TR/xhtml1/).  The -no_xhtml pragma disables this
48200Sstevel@tonic-gatefeature.  Thanks to Michalis Kabrianis <kabrianis@hellug.gr> for this
48210Sstevel@tonic-gatefeature.
48220Sstevel@tonic-gate
4823667Sps156622If start_html()'s -dtd parameter specifies an HTML 2.0 or 3.2 DTD,
4824667Sps156622XHTML will automatically be disabled without needing to use this
4825667Sps156622pragma.
4826667Sps156622
4827*6287Sps156622=item -utf8
4828*6287Sps156622
4829*6287Sps156622This makes CGI.pm treat all parameters as UTF-8 strings. Use this with
4830*6287Sps156622care, as it will interfere with the processing of binary uploads. It
4831*6287Sps156622is better to manually select which fields are expected to return utf-8
4832*6287Sps156622strings and convert them using code like this:
4833*6287Sps156622
4834*6287Sps156622 use Encode;
4835*6287Sps156622 my $arg = decode utf8=>param('foo');
4836*6287Sps156622
48370Sstevel@tonic-gate=item -nph
48380Sstevel@tonic-gate
48390Sstevel@tonic-gateThis makes CGI.pm produce a header appropriate for an NPH (no
48400Sstevel@tonic-gateparsed header) script.  You may need to do other things as well
48410Sstevel@tonic-gateto tell the server that the script is NPH.  See the discussion
48420Sstevel@tonic-gateof NPH scripts below.
48430Sstevel@tonic-gate
48440Sstevel@tonic-gate=item -newstyle_urls
48450Sstevel@tonic-gate
48460Sstevel@tonic-gateSeparate the name=value pairs in CGI parameter query strings with
48470Sstevel@tonic-gatesemicolons rather than ampersands.  For example:
48480Sstevel@tonic-gate
48490Sstevel@tonic-gate   ?name=fred;age=24;favorite_color=3
48500Sstevel@tonic-gate
48510Sstevel@tonic-gateSemicolon-delimited query strings are always accepted, but will not be
48520Sstevel@tonic-gateemitted by self_url() and query_string() unless the -newstyle_urls
48530Sstevel@tonic-gatepragma is specified.
48540Sstevel@tonic-gate
48550Sstevel@tonic-gateThis became the default in version 2.64.
48560Sstevel@tonic-gate
48570Sstevel@tonic-gate=item -oldstyle_urls
48580Sstevel@tonic-gate
48590Sstevel@tonic-gateSeparate the name=value pairs in CGI parameter query strings with
48600Sstevel@tonic-gateampersands rather than semicolons.  This is no longer the default.
48610Sstevel@tonic-gate
48620Sstevel@tonic-gate=item -autoload
48630Sstevel@tonic-gate
48640Sstevel@tonic-gateThis overrides the autoloader so that any function in your program
48650Sstevel@tonic-gatethat is not recognized is referred to CGI.pm for possible evaluation.
48660Sstevel@tonic-gateThis allows you to use all the CGI.pm functions without adding them to
48670Sstevel@tonic-gateyour symbol table, which is of concern for mod_perl users who are
48680Sstevel@tonic-gateworried about memory consumption.  I<Warning:> when
48690Sstevel@tonic-gateI<-autoload> is in effect, you cannot use "poetry mode"
48700Sstevel@tonic-gate(functions without the parenthesis).  Use I<hr()> rather
48710Sstevel@tonic-gatethan I<hr>, or add something like I<use subs qw/hr p header/>
48720Sstevel@tonic-gateto the top of your script.
48730Sstevel@tonic-gate
48740Sstevel@tonic-gate=item -no_debug
48750Sstevel@tonic-gate
48760Sstevel@tonic-gateThis turns off the command-line processing features.  If you want to
48770Sstevel@tonic-gaterun a CGI.pm script from the command line to produce HTML, and you
48780Sstevel@tonic-gatedon't want it to read CGI parameters from the command line or STDIN,
48790Sstevel@tonic-gatethen use this pragma:
48800Sstevel@tonic-gate
48810Sstevel@tonic-gate   use CGI qw(-no_debug :standard);
48820Sstevel@tonic-gate
48830Sstevel@tonic-gate=item -debug
48840Sstevel@tonic-gate
48850Sstevel@tonic-gateThis turns on full debugging.  In addition to reading CGI arguments
48860Sstevel@tonic-gatefrom the command-line processing, CGI.pm will pause and try to read
48870Sstevel@tonic-gatearguments from STDIN, producing the message "(offline mode: enter
48880Sstevel@tonic-gatename=value pairs on standard input)" features.
48890Sstevel@tonic-gate
48900Sstevel@tonic-gateSee the section on debugging for more details.
48910Sstevel@tonic-gate
48920Sstevel@tonic-gate=item -private_tempfiles
48930Sstevel@tonic-gate
48940Sstevel@tonic-gateCGI.pm can process uploaded file. Ordinarily it spools the uploaded
48950Sstevel@tonic-gatefile to a temporary directory, then deletes the file when done.
48960Sstevel@tonic-gateHowever, this opens the risk of eavesdropping as described in the file
48970Sstevel@tonic-gateupload section.  Another CGI script author could peek at this data
48980Sstevel@tonic-gateduring the upload, even if it is confidential information. On Unix
48990Sstevel@tonic-gatesystems, the -private_tempfiles pragma will cause the temporary file
49000Sstevel@tonic-gateto be unlinked as soon as it is opened and before any data is written
49010Sstevel@tonic-gateinto it, reducing, but not eliminating the risk of eavesdropping
49020Sstevel@tonic-gate(there is still a potential race condition).  To make life harder for
49030Sstevel@tonic-gatethe attacker, the program chooses tempfile names by calculating a 32
49040Sstevel@tonic-gatebit checksum of the incoming HTTP headers.
49050Sstevel@tonic-gate
49060Sstevel@tonic-gateTo ensure that the temporary file cannot be read by other CGI scripts,
49070Sstevel@tonic-gateuse suEXEC or a CGI wrapper program to run your script.  The temporary
49080Sstevel@tonic-gatefile is created with mode 0600 (neither world nor group readable).
49090Sstevel@tonic-gate
49100Sstevel@tonic-gateThe temporary directory is selected using the following algorithm:
49110Sstevel@tonic-gate
49120Sstevel@tonic-gate    1. if the current user (e.g. "nobody") has a directory named
49130Sstevel@tonic-gate    "tmp" in its home directory, use that (Unix systems only).
49140Sstevel@tonic-gate
49150Sstevel@tonic-gate    2. if the environment variable TMPDIR exists, use the location
49160Sstevel@tonic-gate    indicated.
49170Sstevel@tonic-gate
49180Sstevel@tonic-gate    3. Otherwise try the locations /usr/tmp, /var/tmp, C:\temp,
49190Sstevel@tonic-gate    /tmp, /temp, ::Temporary Items, and \WWW_ROOT.
49200Sstevel@tonic-gate
49210Sstevel@tonic-gateEach of these locations is checked that it is a directory and is
49220Sstevel@tonic-gatewritable.  If not, the algorithm tries the next choice.
49230Sstevel@tonic-gate
49240Sstevel@tonic-gate=back
49250Sstevel@tonic-gate
49260Sstevel@tonic-gate=head2 SPECIAL FORMS FOR IMPORTING HTML-TAG FUNCTIONS
49270Sstevel@tonic-gate
49280Sstevel@tonic-gateMany of the methods generate HTML tags.  As described below, tag
49290Sstevel@tonic-gatefunctions automatically generate both the opening and closing tags.
49300Sstevel@tonic-gateFor example:
49310Sstevel@tonic-gate
49320Sstevel@tonic-gate  print h1('Level 1 Header');
49330Sstevel@tonic-gate
49340Sstevel@tonic-gateproduces
49350Sstevel@tonic-gate
49360Sstevel@tonic-gate  <h1>Level 1 Header</h1>
49370Sstevel@tonic-gate
49380Sstevel@tonic-gateThere will be some times when you want to produce the start and end
49390Sstevel@tonic-gatetags yourself.  In this case, you can use the form start_I<tag_name>
49400Sstevel@tonic-gateand end_I<tag_name>, as in:
49410Sstevel@tonic-gate
49420Sstevel@tonic-gate  print start_h1,'Level 1 Header',end_h1;
49430Sstevel@tonic-gate
49440Sstevel@tonic-gateWith a few exceptions (described below), start_I<tag_name> and
49450Sstevel@tonic-gateend_I<tag_name> functions are not generated automatically when you
49460Sstevel@tonic-gateI<use CGI>.  However, you can specify the tags you want to generate
49470Sstevel@tonic-gateI<start/end> functions for by putting an asterisk in front of their
49480Sstevel@tonic-gatename, or, alternatively, requesting either "start_I<tag_name>" or
49490Sstevel@tonic-gate"end_I<tag_name>" in the import list.
49500Sstevel@tonic-gate
49510Sstevel@tonic-gateExample:
49520Sstevel@tonic-gate
49530Sstevel@tonic-gate  use CGI qw/:standard *table start_ul/;
49540Sstevel@tonic-gate
49550Sstevel@tonic-gateIn this example, the following functions are generated in addition to
49560Sstevel@tonic-gatethe standard ones:
49570Sstevel@tonic-gate
49580Sstevel@tonic-gate=over 4
49590Sstevel@tonic-gate
49600Sstevel@tonic-gate=item 1. start_table() (generates a <table> tag)
49610Sstevel@tonic-gate
49620Sstevel@tonic-gate=item 2. end_table() (generates a </table> tag)
49630Sstevel@tonic-gate
49640Sstevel@tonic-gate=item 3. start_ul() (generates a <ul> tag)
49650Sstevel@tonic-gate
49660Sstevel@tonic-gate=item 4. end_ul() (generates a </ul> tag)
49670Sstevel@tonic-gate
49680Sstevel@tonic-gate=back
49690Sstevel@tonic-gate
49700Sstevel@tonic-gate=head1 GENERATING DYNAMIC DOCUMENTS
49710Sstevel@tonic-gate
49720Sstevel@tonic-gateMost of CGI.pm's functions deal with creating documents on the fly.
49730Sstevel@tonic-gateGenerally you will produce the HTTP header first, followed by the
49740Sstevel@tonic-gatedocument itself.  CGI.pm provides functions for generating HTTP
49750Sstevel@tonic-gateheaders of various types as well as for generating HTML.  For creating
49760Sstevel@tonic-gateGIF images, see the GD.pm module.
49770Sstevel@tonic-gate
49780Sstevel@tonic-gateEach of these functions produces a fragment of HTML or HTTP which you
49790Sstevel@tonic-gatecan print out directly so that it displays in the browser window,
49800Sstevel@tonic-gateappend to a string, or save to a file for later use.
49810Sstevel@tonic-gate
49820Sstevel@tonic-gate=head2 CREATING A STANDARD HTTP HEADER:
49830Sstevel@tonic-gate
49840Sstevel@tonic-gateNormally the first thing you will do in any CGI script is print out an
49850Sstevel@tonic-gateHTTP header.  This tells the browser what type of document to expect,
49860Sstevel@tonic-gateand gives other optional information, such as the language, expiration
49870Sstevel@tonic-gatedate, and whether to cache the document.  The header can also be
49880Sstevel@tonic-gatemanipulated for special purposes, such as server push and pay per view
49890Sstevel@tonic-gatepages.
49900Sstevel@tonic-gate
4991667Sps156622	print header;
49920Sstevel@tonic-gate
49930Sstevel@tonic-gate	     -or-
49940Sstevel@tonic-gate
4995667Sps156622	print header('image/gif');
49960Sstevel@tonic-gate
49970Sstevel@tonic-gate	     -or-
49980Sstevel@tonic-gate
4999667Sps156622	print header('text/html','204 No response');
50000Sstevel@tonic-gate
50010Sstevel@tonic-gate	     -or-
50020Sstevel@tonic-gate
5003667Sps156622	print header(-type=>'image/gif',
50040Sstevel@tonic-gate			     -nph=>1,
50050Sstevel@tonic-gate			     -status=>'402 Payment required',
50060Sstevel@tonic-gate			     -expires=>'+3d',
50070Sstevel@tonic-gate			     -cookie=>$cookie,
50080Sstevel@tonic-gate                             -charset=>'utf-7',
50090Sstevel@tonic-gate                             -attachment=>'foo.gif',
50100Sstevel@tonic-gate			     -Cost=>'$2.00');
50110Sstevel@tonic-gate
50120Sstevel@tonic-gateheader() returns the Content-type: header.  You can provide your own
50130Sstevel@tonic-gateMIME type if you choose, otherwise it defaults to text/html.  An
50140Sstevel@tonic-gateoptional second parameter specifies the status code and a human-readable
50150Sstevel@tonic-gatemessage.  For example, you can specify 204, "No response" to create a
50160Sstevel@tonic-gatescript that tells the browser to do nothing at all.
50170Sstevel@tonic-gate
50180Sstevel@tonic-gateThe last example shows the named argument style for passing arguments
50190Sstevel@tonic-gateto the CGI methods using named parameters.  Recognized parameters are
50200Sstevel@tonic-gateB<-type>, B<-status>, B<-expires>, and B<-cookie>.  Any other named
50210Sstevel@tonic-gateparameters will be stripped of their initial hyphens and turned into
50220Sstevel@tonic-gateheader fields, allowing you to specify any HTTP header you desire.
50230Sstevel@tonic-gateInternal underscores will be turned into hyphens:
50240Sstevel@tonic-gate
5025667Sps156622    print header(-Content_length=>3002);
50260Sstevel@tonic-gate
50270Sstevel@tonic-gateMost browsers will not cache the output from CGI scripts.  Every time
50280Sstevel@tonic-gatethe browser reloads the page, the script is invoked anew.  You can
50290Sstevel@tonic-gatechange this behavior with the B<-expires> parameter.  When you specify
50300Sstevel@tonic-gatean absolute or relative expiration interval with this parameter, some
50310Sstevel@tonic-gatebrowsers and proxy servers will cache the script's output until the
50320Sstevel@tonic-gateindicated expiration date.  The following forms are all valid for the
50330Sstevel@tonic-gate-expires field:
50340Sstevel@tonic-gate
50350Sstevel@tonic-gate	+30s                              30 seconds from now
50360Sstevel@tonic-gate	+10m                              ten minutes from now
50370Sstevel@tonic-gate	+1h                               one hour from now
50380Sstevel@tonic-gate	-1d                               yesterday (i.e. "ASAP!")
50390Sstevel@tonic-gate	now                               immediately
50400Sstevel@tonic-gate	+3M                               in three months
50410Sstevel@tonic-gate	+10y                              in ten years time
50420Sstevel@tonic-gate	Thursday, 25-Apr-1999 00:40:33 GMT  at the indicated time & date
50430Sstevel@tonic-gate
50440Sstevel@tonic-gateThe B<-cookie> parameter generates a header that tells the browser to provide
50450Sstevel@tonic-gatea "magic cookie" during all subsequent transactions with your script.
50460Sstevel@tonic-gateNetscape cookies have a special format that includes interesting attributes
50470Sstevel@tonic-gatesuch as expiration time.  Use the cookie() method to create and retrieve
50480Sstevel@tonic-gatesession cookies.
50490Sstevel@tonic-gate
50500Sstevel@tonic-gateThe B<-nph> parameter, if set to a true value, will issue the correct
50510Sstevel@tonic-gateheaders to work with a NPH (no-parse-header) script.  This is important
50520Sstevel@tonic-gateto use with certain servers that expect all their scripts to be NPH.
50530Sstevel@tonic-gate
50540Sstevel@tonic-gateThe B<-charset> parameter can be used to control the character set
50550Sstevel@tonic-gatesent to the browser.  If not provided, defaults to ISO-8859-1.  As a
50560Sstevel@tonic-gateside effect, this sets the charset() method as well.
50570Sstevel@tonic-gate
50580Sstevel@tonic-gateThe B<-attachment> parameter can be used to turn the page into an
50590Sstevel@tonic-gateattachment.  Instead of displaying the page, some browsers will prompt
50600Sstevel@tonic-gatethe user to save it to disk.  The value of the argument is the
50610Sstevel@tonic-gatesuggested name for the saved file.  In order for this to work, you may
50620Sstevel@tonic-gatehave to set the B<-type> to "application/octet-stream".
50630Sstevel@tonic-gate
50640Sstevel@tonic-gateThe B<-p3p> parameter will add a P3P tag to the outgoing header.  The
50650Sstevel@tonic-gateparameter can be an arrayref or a space-delimited string of P3P tags.
50660Sstevel@tonic-gateFor example:
50670Sstevel@tonic-gate
50680Sstevel@tonic-gate   print header(-p3p=>[qw(CAO DSP LAW CURa)]);
50690Sstevel@tonic-gate   print header(-p3p=>'CAO DSP LAW CURa');
50700Sstevel@tonic-gate
50710Sstevel@tonic-gateIn either case, the outgoing header will be formatted as:
50720Sstevel@tonic-gate
50730Sstevel@tonic-gate  P3P: policyref="/w3c/p3p.xml" cp="CAO DSP LAW CURa"
50740Sstevel@tonic-gate
50750Sstevel@tonic-gate=head2 GENERATING A REDIRECTION HEADER
50760Sstevel@tonic-gate
5077667Sps156622   print redirect('http://somewhere.else/in/movie/land');
50780Sstevel@tonic-gate
50790Sstevel@tonic-gateSometimes you don't want to produce a document yourself, but simply
50800Sstevel@tonic-gateredirect the browser elsewhere, perhaps choosing a URL based on the
50810Sstevel@tonic-gatetime of day or the identity of the user.
50820Sstevel@tonic-gate
50830Sstevel@tonic-gateThe redirect() function redirects the browser to a different URL.  If
50840Sstevel@tonic-gateyou use redirection like this, you should B<not> print out a header as
50850Sstevel@tonic-gatewell.
50860Sstevel@tonic-gate
50870Sstevel@tonic-gateYou should always use full URLs (including the http: or ftp: part) in
50880Sstevel@tonic-gateredirection requests.  Relative URLs will not work correctly.
50890Sstevel@tonic-gate
50900Sstevel@tonic-gateYou can also use named arguments:
50910Sstevel@tonic-gate
5092667Sps156622    print redirect(-uri=>'http://somewhere.else/in/movie/land',
5093667Sps156622			   -nph=>1,
5094667Sps156622                           -status=>301);
50950Sstevel@tonic-gate
50960Sstevel@tonic-gateThe B<-nph> parameter, if set to a true value, will issue the correct
50970Sstevel@tonic-gateheaders to work with a NPH (no-parse-header) script.  This is important
50980Sstevel@tonic-gateto use with certain servers, such as Microsoft IIS, which
50990Sstevel@tonic-gateexpect all their scripts to be NPH.
51000Sstevel@tonic-gate
5101667Sps156622The B<-status> parameter will set the status of the redirect.  HTTP
5102667Sps156622defines three different possible redirection status codes:
5103667Sps156622
5104667Sps156622     301 Moved Permanently
5105667Sps156622     302 Found
5106667Sps156622     303 See Other
5107667Sps156622
5108667Sps156622The default if not specified is 302, which means "moved temporarily."
5109667Sps156622You may change the status to another status code if you wish.  Be
5110667Sps156622advised that changing the status to anything other than 301, 302 or
5111667Sps156622303 will probably break redirection.
5112667Sps156622
51130Sstevel@tonic-gate=head2 CREATING THE HTML DOCUMENT HEADER
51140Sstevel@tonic-gate
5115667Sps156622   print start_html(-title=>'Secrets of the Pyramids',
51160Sstevel@tonic-gate			    -author=>'fred@capricorn.org',
51170Sstevel@tonic-gate			    -base=>'true',
51180Sstevel@tonic-gate			    -target=>'_blank',
51190Sstevel@tonic-gate			    -meta=>{'keywords'=>'pharaoh secret mummy',
51200Sstevel@tonic-gate				    'copyright'=>'copyright 1996 King Tut'},
51210Sstevel@tonic-gate			    -style=>{'src'=>'/styles/style1.css'},
51220Sstevel@tonic-gate			    -BGCOLOR=>'blue');
51230Sstevel@tonic-gate
51240Sstevel@tonic-gateAfter creating the HTTP header, most CGI scripts will start writing
51250Sstevel@tonic-gateout an HTML document.  The start_html() routine creates the top of the
51260Sstevel@tonic-gatepage, along with a lot of optional information that controls the
51270Sstevel@tonic-gatepage's appearance and behavior.
51280Sstevel@tonic-gate
51290Sstevel@tonic-gateThis method returns a canned HTML header and the opening <body> tag.
51300Sstevel@tonic-gateAll parameters are optional.  In the named parameter form, recognized
51310Sstevel@tonic-gateparameters are -title, -author, -base, -xbase, -dtd, -lang and -target
51320Sstevel@tonic-gate(see below for the explanation).  Any additional parameters you
51330Sstevel@tonic-gateprovide, such as the Netscape unofficial BGCOLOR attribute, are added
51340Sstevel@tonic-gateto the <body> tag.  Additional parameters must be proceeded by a
51350Sstevel@tonic-gatehyphen.
51360Sstevel@tonic-gate
51370Sstevel@tonic-gateThe argument B<-xbase> allows you to provide an HREF for the <base> tag
51380Sstevel@tonic-gatedifferent from the current location, as in
51390Sstevel@tonic-gate
51400Sstevel@tonic-gate    -xbase=>"http://home.mcom.com/"
51410Sstevel@tonic-gate
51420Sstevel@tonic-gateAll relative links will be interpreted relative to this tag.
51430Sstevel@tonic-gate
51440Sstevel@tonic-gateThe argument B<-target> allows you to provide a default target frame
51450Sstevel@tonic-gatefor all the links and fill-out forms on the page.  B<This is a
51460Sstevel@tonic-gatenon-standard HTTP feature which only works with Netscape browsers!>
51470Sstevel@tonic-gateSee the Netscape documentation on frames for details of how to
51480Sstevel@tonic-gatemanipulate this.
51490Sstevel@tonic-gate
51500Sstevel@tonic-gate    -target=>"answer_window"
51510Sstevel@tonic-gate
51520Sstevel@tonic-gateAll relative links will be interpreted relative to this tag.
51530Sstevel@tonic-gateYou add arbitrary meta information to the header with the B<-meta>
51540Sstevel@tonic-gateargument.  This argument expects a reference to an associative array
51550Sstevel@tonic-gatecontaining name/value pairs of meta information.  These will be turned
51560Sstevel@tonic-gateinto a series of header <meta> tags that look something like this:
51570Sstevel@tonic-gate
51580Sstevel@tonic-gate    <meta name="keywords" content="pharaoh secret mummy">
51590Sstevel@tonic-gate    <meta name="description" content="copyright 1996 King Tut">
51600Sstevel@tonic-gate
51610Sstevel@tonic-gateTo create an HTTP-EQUIV type of <meta> tag, use B<-head>, described
51620Sstevel@tonic-gatebelow.
51630Sstevel@tonic-gate
51640Sstevel@tonic-gateThe B<-style> argument is used to incorporate cascading stylesheets
51650Sstevel@tonic-gateinto your code.  See the section on CASCADING STYLESHEETS for more
51660Sstevel@tonic-gateinformation.
51670Sstevel@tonic-gate
51680Sstevel@tonic-gateThe B<-lang> argument is used to incorporate a language attribute into
5169667Sps156622the <html> tag.  For example:
51700Sstevel@tonic-gate
51710Sstevel@tonic-gate    print $q->start_html(-lang=>'fr-CA');
51720Sstevel@tonic-gate
5173667Sps156622The default if not specified is "en-US" for US English, unless the
5174667Sps156622-dtd parameter specifies an HTML 2.0 or 3.2 DTD, in which case the
5175667Sps156622lang attribute is left off.  You can force the lang attribute to left
5176667Sps156622off in other cases by passing an empty string (-lang=>'').
51770Sstevel@tonic-gate
51780Sstevel@tonic-gateThe B<-encoding> argument can be used to specify the character set for
51790Sstevel@tonic-gateXHTML.  It defaults to iso-8859-1 if not specified.
51800Sstevel@tonic-gate
5181667Sps156622The B<-declare_xml> argument, when used in conjunction with XHTML,
5182667Sps156622will put a <?xml> declaration at the top of the HTML header. The sole
5183667Sps156622purpose of this declaration is to declare the character set
5184667Sps156622encoding. In the absence of -declare_xml, the output HTML will contain
5185667Sps156622a <meta> tag that specifies the encoding, allowing the HTML to pass
5186667Sps156622most validators.  The default for -declare_xml is false.
5187667Sps156622
51880Sstevel@tonic-gateYou can place other arbitrary HTML elements to the <head> section with the
51890Sstevel@tonic-gateB<-head> tag.  For example, to place the rarely-used <link> element in the
51900Sstevel@tonic-gatehead section, use this:
51910Sstevel@tonic-gate
51920Sstevel@tonic-gate    print start_html(-head=>Link({-rel=>'next',
51930Sstevel@tonic-gate		                  -href=>'http://www.capricorn.com/s2.html'}));
51940Sstevel@tonic-gate
51950Sstevel@tonic-gateTo incorporate multiple HTML elements into the <head> section, just pass an
51960Sstevel@tonic-gatearray reference:
51970Sstevel@tonic-gate
51980Sstevel@tonic-gate    print start_html(-head=>[
51990Sstevel@tonic-gate                             Link({-rel=>'next',
52000Sstevel@tonic-gate				   -href=>'http://www.capricorn.com/s2.html'}),
52010Sstevel@tonic-gate		             Link({-rel=>'previous',
52020Sstevel@tonic-gate				   -href=>'http://www.capricorn.com/s1.html'})
52030Sstevel@tonic-gate			     ]
52040Sstevel@tonic-gate		     );
52050Sstevel@tonic-gate
52060Sstevel@tonic-gateAnd here's how to create an HTTP-EQUIV <meta> tag:
52070Sstevel@tonic-gate
52080Sstevel@tonic-gate      print start_html(-head=>meta({-http_equiv => 'Content-Type',
52090Sstevel@tonic-gate                                    -content    => 'text/html'}))
52100Sstevel@tonic-gate
52110Sstevel@tonic-gate
52120Sstevel@tonic-gateJAVASCRIPTING: The B<-script>, B<-noScript>, B<-onLoad>,
52130Sstevel@tonic-gateB<-onMouseOver>, B<-onMouseOut> and B<-onUnload> parameters are used
52140Sstevel@tonic-gateto add Netscape JavaScript calls to your pages.  B<-script> should
52150Sstevel@tonic-gatepoint to a block of text containing JavaScript function definitions.
52160Sstevel@tonic-gateThis block will be placed within a <script> block inside the HTML (not
52170Sstevel@tonic-gateHTTP) header.  The block is placed in the header in order to give your
52180Sstevel@tonic-gatepage a fighting chance of having all its JavaScript functions in place
52190Sstevel@tonic-gateeven if the user presses the stop button before the page has loaded
52200Sstevel@tonic-gatecompletely.  CGI.pm attempts to format the script in such a way that
52210Sstevel@tonic-gateJavaScript-naive browsers will not choke on the code: unfortunately
52220Sstevel@tonic-gatethere are some browsers, such as Chimera for Unix, that get confused
52230Sstevel@tonic-gateby it nevertheless.
52240Sstevel@tonic-gate
52250Sstevel@tonic-gateThe B<-onLoad> and B<-onUnload> parameters point to fragments of JavaScript
52260Sstevel@tonic-gatecode to execute when the page is respectively opened and closed by the
52270Sstevel@tonic-gatebrowser.  Usually these parameters are calls to functions defined in the
52280Sstevel@tonic-gateB<-script> field:
52290Sstevel@tonic-gate
52300Sstevel@tonic-gate      $query = new CGI;
5231667Sps156622      print header;
52320Sstevel@tonic-gate      $JSCRIPT=<<END;
52330Sstevel@tonic-gate      // Ask a silly question
52340Sstevel@tonic-gate      function riddle_me_this() {
52350Sstevel@tonic-gate	 var r = prompt("What walks on four legs in the morning, " +
52360Sstevel@tonic-gate		       "two legs in the afternoon, " +
52370Sstevel@tonic-gate		       "and three legs in the evening?");
52380Sstevel@tonic-gate	 response(r);
52390Sstevel@tonic-gate      }
52400Sstevel@tonic-gate      // Get a silly answer
52410Sstevel@tonic-gate      function response(answer) {
52420Sstevel@tonic-gate	 if (answer == "man")
52430Sstevel@tonic-gate	    alert("Right you are!");
52440Sstevel@tonic-gate	 else
52450Sstevel@tonic-gate	    alert("Wrong!  Guess again.");
52460Sstevel@tonic-gate      }
52470Sstevel@tonic-gate      END
5248667Sps156622      print start_html(-title=>'The Riddle of the Sphinx',
52490Sstevel@tonic-gate			       -script=>$JSCRIPT);
52500Sstevel@tonic-gate
52510Sstevel@tonic-gateUse the B<-noScript> parameter to pass some HTML text that will be displayed on
52520Sstevel@tonic-gatebrowsers that do not have JavaScript (or browsers where JavaScript is turned
52530Sstevel@tonic-gateoff).
52540Sstevel@tonic-gate
5255*6287Sps156622The <script> tag, has several attributes including "type" and src.
5256*6287Sps156622The latter is particularly interesting, as it allows you to keep the
5257*6287Sps156622JavaScript code in a file or CGI script rather than cluttering up each
5258*6287Sps156622page with the source.  To use these attributes pass a HASH reference
5259*6287Sps156622in the B<-script> parameter containing one or more of -type, -src, or
5260*6287Sps156622-code:
52610Sstevel@tonic-gate
52620Sstevel@tonic-gate    print $q->start_html(-title=>'The Riddle of the Sphinx',
5263*6287Sps156622			 -script=>{-type=>'JAVASCRIPT',
52640Sstevel@tonic-gate                                   -src=>'/javascript/sphinx.js'}
52650Sstevel@tonic-gate			 );
52660Sstevel@tonic-gate
52670Sstevel@tonic-gate    print $q->(-title=>'The Riddle of the Sphinx',
5268*6287Sps156622	       -script=>{-type=>'PERLSCRIPT',
52690Sstevel@tonic-gate			 -code=>'print "hello world!\n;"'}
52700Sstevel@tonic-gate	       );
52710Sstevel@tonic-gate
52720Sstevel@tonic-gate
52730Sstevel@tonic-gateA final feature allows you to incorporate multiple <script> sections into the
52740Sstevel@tonic-gateheader.  Just pass the list of script sections as an array reference.
52750Sstevel@tonic-gatethis allows you to specify different source files for different dialects
5276*6287Sps156622of JavaScript.  Example:
52770Sstevel@tonic-gate
52780Sstevel@tonic-gate     print $q->start_html(-title=>'The Riddle of the Sphinx',
52790Sstevel@tonic-gate                          -script=>[
5280*6287Sps156622                                    { -type => 'text/javascript',
52810Sstevel@tonic-gate                                      -src      => '/javascript/utilities10.js'
52820Sstevel@tonic-gate                                    },
5283*6287Sps156622                                    { -type => 'text/javascript',
52840Sstevel@tonic-gate                                      -src      => '/javascript/utilities11.js'
52850Sstevel@tonic-gate                                    },
5286*6287Sps156622                                    { -type => 'text/jscript',
52870Sstevel@tonic-gate                                      -src      => '/javascript/utilities12.js'
52880Sstevel@tonic-gate                                    },
5289*6287Sps156622                                    { -type => 'text/ecmascript',
52900Sstevel@tonic-gate                                      -src      => '/javascript/utilities219.js'
52910Sstevel@tonic-gate                                    }
52920Sstevel@tonic-gate                                 ]
52930Sstevel@tonic-gate                             );
52940Sstevel@tonic-gate
5295*6287Sps156622The option "-language" is a synonym for -type, and is supported for
5296*6287Sps156622backwad compatibility.
52970Sstevel@tonic-gate
52980Sstevel@tonic-gateThe old-style positional parameters are as follows:
52990Sstevel@tonic-gate
53000Sstevel@tonic-gate=over 4
53010Sstevel@tonic-gate
53020Sstevel@tonic-gate=item B<Parameters:>
53030Sstevel@tonic-gate
53040Sstevel@tonic-gate=item 1.
53050Sstevel@tonic-gate
53060Sstevel@tonic-gateThe title
53070Sstevel@tonic-gate
53080Sstevel@tonic-gate=item 2.
53090Sstevel@tonic-gate
53100Sstevel@tonic-gateThe author's e-mail address (will create a <link rev="MADE"> tag if present
53110Sstevel@tonic-gate
53120Sstevel@tonic-gate=item 3.
53130Sstevel@tonic-gate
53140Sstevel@tonic-gateA 'true' flag if you want to include a <base> tag in the header.  This
53150Sstevel@tonic-gatehelps resolve relative addresses to absolute ones when the document is moved,
53160Sstevel@tonic-gatebut makes the document hierarchy non-portable.  Use with care!
53170Sstevel@tonic-gate
53180Sstevel@tonic-gate=item 4, 5, 6...
53190Sstevel@tonic-gate
53200Sstevel@tonic-gateAny other parameters you want to include in the <body> tag.  This is a good
53210Sstevel@tonic-gateplace to put Netscape extensions, such as colors and wallpaper patterns.
53220Sstevel@tonic-gate
53230Sstevel@tonic-gate=back
53240Sstevel@tonic-gate
53250Sstevel@tonic-gate=head2 ENDING THE HTML DOCUMENT:
53260Sstevel@tonic-gate
5327667Sps156622	print end_html
53280Sstevel@tonic-gate
53290Sstevel@tonic-gateThis ends an HTML document by printing the </body></html> tags.
53300Sstevel@tonic-gate
53310Sstevel@tonic-gate=head2 CREATING A SELF-REFERENCING URL THAT PRESERVES STATE INFORMATION:
53320Sstevel@tonic-gate
5333667Sps156622    $myself = self_url;
53340Sstevel@tonic-gate    print q(<a href="$myself">I'm talking to myself.</a>);
53350Sstevel@tonic-gate
53360Sstevel@tonic-gateself_url() will return a URL, that, when selected, will reinvoke
53370Sstevel@tonic-gatethis script with all its state information intact.  This is most
53380Sstevel@tonic-gateuseful when you want to jump around within the document using
53390Sstevel@tonic-gateinternal anchors but you don't want to disrupt the current contents
53400Sstevel@tonic-gateof the form(s).  Something like this will do the trick.
53410Sstevel@tonic-gate
5342667Sps156622     $myself = self_url;
53430Sstevel@tonic-gate     print "<a href=\"$myself#table1\">See table 1</a>";
53440Sstevel@tonic-gate     print "<a href=\"$myself#table2\">See table 2</a>";
53450Sstevel@tonic-gate     print "<a href=\"$myself#yourself\">See for yourself</a>";
53460Sstevel@tonic-gate
53470Sstevel@tonic-gateIf you want more control over what's returned, using the B<url()>
53480Sstevel@tonic-gatemethod instead.
53490Sstevel@tonic-gate
53500Sstevel@tonic-gateYou can also retrieve the unprocessed query string with query_string():
53510Sstevel@tonic-gate
5352667Sps156622    $the_string = query_string;
53530Sstevel@tonic-gate
53540Sstevel@tonic-gate=head2 OBTAINING THE SCRIPT'S URL
53550Sstevel@tonic-gate
5356667Sps156622    $full_url      = url();
5357667Sps156622    $full_url      = url(-full=>1);  #alternative syntax
5358667Sps156622    $relative_url  = url(-relative=>1);
5359667Sps156622    $absolute_url  = url(-absolute=>1);
5360667Sps156622    $url_with_path = url(-path_info=>1);
5361667Sps156622    $url_with_path_and_query = url(-path_info=>1,-query=>1);
5362667Sps156622    $netloc        = url(-base => 1);
53630Sstevel@tonic-gate
53640Sstevel@tonic-gateB<url()> returns the script's URL in a variety of formats.  Called
53650Sstevel@tonic-gatewithout any arguments, it returns the full form of the URL, including
53660Sstevel@tonic-gatehost name and port number
53670Sstevel@tonic-gate
53680Sstevel@tonic-gate    http://your.host.com/path/to/script.cgi
53690Sstevel@tonic-gate
53700Sstevel@tonic-gateYou can modify this format with the following named arguments:
53710Sstevel@tonic-gate
53720Sstevel@tonic-gate=over 4
53730Sstevel@tonic-gate
53740Sstevel@tonic-gate=item B<-absolute>
53750Sstevel@tonic-gate
53760Sstevel@tonic-gateIf true, produce an absolute URL, e.g.
53770Sstevel@tonic-gate
53780Sstevel@tonic-gate    /path/to/script.cgi
53790Sstevel@tonic-gate
53800Sstevel@tonic-gate=item B<-relative>
53810Sstevel@tonic-gate
53820Sstevel@tonic-gateProduce a relative URL.  This is useful if you want to reinvoke your
53830Sstevel@tonic-gatescript with different parameters. For example:
53840Sstevel@tonic-gate
53850Sstevel@tonic-gate    script.cgi
53860Sstevel@tonic-gate
53870Sstevel@tonic-gate=item B<-full>
53880Sstevel@tonic-gate
53890Sstevel@tonic-gateProduce the full URL, exactly as if called without any arguments.
53900Sstevel@tonic-gateThis overrides the -relative and -absolute arguments.
53910Sstevel@tonic-gate
53920Sstevel@tonic-gate=item B<-path> (B<-path_info>)
53930Sstevel@tonic-gate
53940Sstevel@tonic-gateAppend the additional path information to the URL.  This can be
53950Sstevel@tonic-gatecombined with B<-full>, B<-absolute> or B<-relative>.  B<-path_info>
53960Sstevel@tonic-gateis provided as a synonym.
53970Sstevel@tonic-gate
53980Sstevel@tonic-gate=item B<-query> (B<-query_string>)
53990Sstevel@tonic-gate
54000Sstevel@tonic-gateAppend the query string to the URL.  This can be combined with
54010Sstevel@tonic-gateB<-full>, B<-absolute> or B<-relative>.  B<-query_string> is provided
54020Sstevel@tonic-gateas a synonym.
54030Sstevel@tonic-gate
54040Sstevel@tonic-gate=item B<-base>
54050Sstevel@tonic-gate
54060Sstevel@tonic-gateGenerate just the protocol and net location, as in http://www.foo.com:8000
54070Sstevel@tonic-gate
5408*6287Sps156622=item B<-rewrite>
5409*6287Sps156622
5410*6287Sps156622If Apache's mod_rewrite is turned on, then the script name and path
5411*6287Sps156622info probably won't match the request that the user sent. Set
5412*6287Sps156622-rewrite=>1 (default) to return URLs that match what the user sent
5413*6287Sps156622(the original request URI). Set -rewrite->0 to return URLs that match
5414*6287Sps156622the URL after mod_rewrite's rules have run. Because the additional
5415*6287Sps156622path information only makes sense in the context of the rewritten URL,
5416*6287Sps156622-rewrite is set to false when you request path info in the URL.
5417*6287Sps156622
54180Sstevel@tonic-gate=back
54190Sstevel@tonic-gate
54200Sstevel@tonic-gate=head2 MIXING POST AND URL PARAMETERS
54210Sstevel@tonic-gate
5422667Sps156622   $color = url_param('color');
54230Sstevel@tonic-gate
54240Sstevel@tonic-gateIt is possible for a script to receive CGI parameters in the URL as
54250Sstevel@tonic-gatewell as in the fill-out form by creating a form that POSTs to a URL
54260Sstevel@tonic-gatecontaining a query string (a "?" mark followed by arguments).  The
54270Sstevel@tonic-gateB<param()> method will always return the contents of the POSTed
54280Sstevel@tonic-gatefill-out form, ignoring the URL's query string.  To retrieve URL
54290Sstevel@tonic-gateparameters, call the B<url_param()> method.  Use it in the same way as
54300Sstevel@tonic-gateB<param()>.  The main difference is that it allows you to read the
54310Sstevel@tonic-gateparameters, but not set them.
54320Sstevel@tonic-gate
54330Sstevel@tonic-gate
54340Sstevel@tonic-gateUnder no circumstances will the contents of the URL query string
54350Sstevel@tonic-gateinterfere with similarly-named CGI parameters in POSTed forms.  If you
54360Sstevel@tonic-gatetry to mix a URL query string with a form submitted with the GET
54370Sstevel@tonic-gatemethod, the results will not be what you expect.
54380Sstevel@tonic-gate
54390Sstevel@tonic-gate=head1 CREATING STANDARD HTML ELEMENTS:
54400Sstevel@tonic-gate
54410Sstevel@tonic-gateCGI.pm defines general HTML shortcut methods for most, if not all of
54420Sstevel@tonic-gatethe HTML 3 and HTML 4 tags.  HTML shortcuts are named after a single
54430Sstevel@tonic-gateHTML element and return a fragment of HTML text that you can then
54440Sstevel@tonic-gateprint or manipulate as you like.  Each shortcut returns a fragment of
54450Sstevel@tonic-gateHTML code that you can append to a string, save to a file, or, most
54460Sstevel@tonic-gatecommonly, print out so that it displays in the browser window.
54470Sstevel@tonic-gate
54480Sstevel@tonic-gateThis example shows how to use the HTML methods:
54490Sstevel@tonic-gate
54500Sstevel@tonic-gate   print $q->blockquote(
54510Sstevel@tonic-gate		     "Many years ago on the island of",
54520Sstevel@tonic-gate		     $q->a({href=>"http://crete.org/"},"Crete"),
54530Sstevel@tonic-gate		     "there lived a Minotaur named",
54540Sstevel@tonic-gate		     $q->strong("Fred."),
54550Sstevel@tonic-gate		    ),
54560Sstevel@tonic-gate       $q->hr;
54570Sstevel@tonic-gate
54580Sstevel@tonic-gateThis results in the following HTML code (extra newlines have been
54590Sstevel@tonic-gateadded for readability):
54600Sstevel@tonic-gate
54610Sstevel@tonic-gate   <blockquote>
54620Sstevel@tonic-gate   Many years ago on the island of
54630Sstevel@tonic-gate   <a href="http://crete.org/">Crete</a> there lived
54640Sstevel@tonic-gate   a minotaur named <strong>Fred.</strong>
54650Sstevel@tonic-gate   </blockquote>
54660Sstevel@tonic-gate   <hr>
54670Sstevel@tonic-gate
54680Sstevel@tonic-gateIf you find the syntax for calling the HTML shortcuts awkward, you can
54690Sstevel@tonic-gateimport them into your namespace and dispense with the object syntax
54700Sstevel@tonic-gatecompletely (see the next section for more details):
54710Sstevel@tonic-gate
54720Sstevel@tonic-gate   use CGI ':standard';
54730Sstevel@tonic-gate   print blockquote(
54740Sstevel@tonic-gate      "Many years ago on the island of",
54750Sstevel@tonic-gate      a({href=>"http://crete.org/"},"Crete"),
54760Sstevel@tonic-gate      "there lived a minotaur named",
54770Sstevel@tonic-gate      strong("Fred."),
54780Sstevel@tonic-gate      ),
54790Sstevel@tonic-gate      hr;
54800Sstevel@tonic-gate
54810Sstevel@tonic-gate=head2 PROVIDING ARGUMENTS TO HTML SHORTCUTS
54820Sstevel@tonic-gate
54830Sstevel@tonic-gateThe HTML methods will accept zero, one or multiple arguments.  If you
54840Sstevel@tonic-gateprovide no arguments, you get a single tag:
54850Sstevel@tonic-gate
54860Sstevel@tonic-gate   print hr;  	#  <hr>
54870Sstevel@tonic-gate
54880Sstevel@tonic-gateIf you provide one or more string arguments, they are concatenated
54890Sstevel@tonic-gatetogether with spaces and placed between opening and closing tags:
54900Sstevel@tonic-gate
54910Sstevel@tonic-gate   print h1("Chapter","1"); # <h1>Chapter 1</h1>"
54920Sstevel@tonic-gate
54930Sstevel@tonic-gateIf the first argument is an associative array reference, then the keys
54940Sstevel@tonic-gateand values of the associative array become the HTML tag's attributes:
54950Sstevel@tonic-gate
54960Sstevel@tonic-gate   print a({-href=>'fred.html',-target=>'_new'},
54970Sstevel@tonic-gate      "Open a new frame");
54980Sstevel@tonic-gate
54990Sstevel@tonic-gate	    <a href="fred.html",target="_new">Open a new frame</a>
55000Sstevel@tonic-gate
55010Sstevel@tonic-gateYou may dispense with the dashes in front of the attribute names if
55020Sstevel@tonic-gateyou prefer:
55030Sstevel@tonic-gate
55040Sstevel@tonic-gate   print img {src=>'fred.gif',align=>'LEFT'};
55050Sstevel@tonic-gate
55060Sstevel@tonic-gate	   <img align="LEFT" src="fred.gif">
55070Sstevel@tonic-gate
55080Sstevel@tonic-gateSometimes an HTML tag attribute has no argument.  For example, ordered
55090Sstevel@tonic-gatelists can be marked as COMPACT.  The syntax for this is an argument that
55100Sstevel@tonic-gatethat points to an undef string:
55110Sstevel@tonic-gate
55120Sstevel@tonic-gate   print ol({compact=>undef},li('one'),li('two'),li('three'));
55130Sstevel@tonic-gate
55140Sstevel@tonic-gatePrior to CGI.pm version 2.41, providing an empty ('') string as an
55150Sstevel@tonic-gateattribute argument was the same as providing undef.  However, this has
55160Sstevel@tonic-gatechanged in order to accommodate those who want to create tags of the form
55170Sstevel@tonic-gate<img alt="">.  The difference is shown in these two pieces of code:
55180Sstevel@tonic-gate
55190Sstevel@tonic-gate   CODE                   RESULT
55200Sstevel@tonic-gate   img({alt=>undef})      <img alt>
55210Sstevel@tonic-gate   img({alt=>''})         <img alt="">
55220Sstevel@tonic-gate
55230Sstevel@tonic-gate=head2 THE DISTRIBUTIVE PROPERTY OF HTML SHORTCUTS
55240Sstevel@tonic-gate
55250Sstevel@tonic-gateOne of the cool features of the HTML shortcuts is that they are
55260Sstevel@tonic-gatedistributive.  If you give them an argument consisting of a
55270Sstevel@tonic-gateB<reference> to a list, the tag will be distributed across each
55280Sstevel@tonic-gateelement of the list.  For example, here's one way to make an ordered
55290Sstevel@tonic-gatelist:
55300Sstevel@tonic-gate
55310Sstevel@tonic-gate   print ul(
55320Sstevel@tonic-gate             li({-type=>'disc'},['Sneezy','Doc','Sleepy','Happy'])
55330Sstevel@tonic-gate           );
55340Sstevel@tonic-gate
55350Sstevel@tonic-gateThis example will result in HTML output that looks like this:
55360Sstevel@tonic-gate
55370Sstevel@tonic-gate   <ul>
55380Sstevel@tonic-gate     <li type="disc">Sneezy</li>
55390Sstevel@tonic-gate     <li type="disc">Doc</li>
55400Sstevel@tonic-gate     <li type="disc">Sleepy</li>
55410Sstevel@tonic-gate     <li type="disc">Happy</li>
55420Sstevel@tonic-gate   </ul>
55430Sstevel@tonic-gate
55440Sstevel@tonic-gateThis is extremely useful for creating tables.  For example:
55450Sstevel@tonic-gate
55460Sstevel@tonic-gate   print table({-border=>undef},
55470Sstevel@tonic-gate           caption('When Should You Eat Your Vegetables?'),
55480Sstevel@tonic-gate           Tr({-align=>CENTER,-valign=>TOP},
55490Sstevel@tonic-gate           [
55500Sstevel@tonic-gate              th(['Vegetable', 'Breakfast','Lunch','Dinner']),
55510Sstevel@tonic-gate              td(['Tomatoes' , 'no', 'yes', 'yes']),
55520Sstevel@tonic-gate              td(['Broccoli' , 'no', 'no',  'yes']),
55530Sstevel@tonic-gate              td(['Onions'   , 'yes','yes', 'yes'])
55540Sstevel@tonic-gate           ]
55550Sstevel@tonic-gate           )
55560Sstevel@tonic-gate        );
55570Sstevel@tonic-gate
55580Sstevel@tonic-gate=head2 HTML SHORTCUTS AND LIST INTERPOLATION
55590Sstevel@tonic-gate
55600Sstevel@tonic-gateConsider this bit of code:
55610Sstevel@tonic-gate
55620Sstevel@tonic-gate   print blockquote(em('Hi'),'mom!'));
55630Sstevel@tonic-gate
55640Sstevel@tonic-gateIt will ordinarily return the string that you probably expect, namely:
55650Sstevel@tonic-gate
55660Sstevel@tonic-gate   <blockquote><em>Hi</em> mom!</blockquote>
55670Sstevel@tonic-gate
55680Sstevel@tonic-gateNote the space between the element "Hi" and the element "mom!".
55690Sstevel@tonic-gateCGI.pm puts the extra space there using array interpolation, which is
55700Sstevel@tonic-gatecontrolled by the magic $" variable.  Sometimes this extra space is
55710Sstevel@tonic-gatenot what you want, for example, when you are trying to align a series
55720Sstevel@tonic-gateof images.  In this case, you can simply change the value of $" to an
55730Sstevel@tonic-gateempty string.
55740Sstevel@tonic-gate
55750Sstevel@tonic-gate   {
55760Sstevel@tonic-gate      local($") = '';
55770Sstevel@tonic-gate      print blockquote(em('Hi'),'mom!'));
55780Sstevel@tonic-gate    }
55790Sstevel@tonic-gate
55800Sstevel@tonic-gateI suggest you put the code in a block as shown here.  Otherwise the
55810Sstevel@tonic-gatechange to $" will affect all subsequent code until you explicitly
55820Sstevel@tonic-gatereset it.
55830Sstevel@tonic-gate
55840Sstevel@tonic-gate=head2 NON-STANDARD HTML SHORTCUTS
55850Sstevel@tonic-gate
55860Sstevel@tonic-gateA few HTML tags don't follow the standard pattern for various
55870Sstevel@tonic-gatereasons.
55880Sstevel@tonic-gate
55890Sstevel@tonic-gateB<comment()> generates an HTML comment (<!-- comment -->).  Call it
55900Sstevel@tonic-gatelike
55910Sstevel@tonic-gate
55920Sstevel@tonic-gate    print comment('here is my comment');
55930Sstevel@tonic-gate
55940Sstevel@tonic-gateBecause of conflicts with built-in Perl functions, the following functions
55950Sstevel@tonic-gatebegin with initial caps:
55960Sstevel@tonic-gate
55970Sstevel@tonic-gate    Select
55980Sstevel@tonic-gate    Tr
55990Sstevel@tonic-gate    Link
56000Sstevel@tonic-gate    Delete
56010Sstevel@tonic-gate    Accept
56020Sstevel@tonic-gate    Sub
56030Sstevel@tonic-gate
56040Sstevel@tonic-gateIn addition, start_html(), end_html(), start_form(), end_form(),
56050Sstevel@tonic-gatestart_multipart_form() and all the fill-out form tags are special.
56060Sstevel@tonic-gateSee their respective sections.
56070Sstevel@tonic-gate
56080Sstevel@tonic-gate=head2 AUTOESCAPING HTML
56090Sstevel@tonic-gate
56100Sstevel@tonic-gateBy default, all HTML that is emitted by the form-generating functions
56110Sstevel@tonic-gateis passed through a function called escapeHTML():
56120Sstevel@tonic-gate
56130Sstevel@tonic-gate=over 4
56140Sstevel@tonic-gate
56150Sstevel@tonic-gate=item $escaped_string = escapeHTML("unescaped string");
56160Sstevel@tonic-gate
56170Sstevel@tonic-gateEscape HTML formatting characters in a string.
56180Sstevel@tonic-gate
56190Sstevel@tonic-gate=back
56200Sstevel@tonic-gate
56210Sstevel@tonic-gateProvided that you have specified a character set of ISO-8859-1 (the
56220Sstevel@tonic-gatedefault), the standard HTML escaping rules will be used.  The "<"
56230Sstevel@tonic-gatecharacter becomes "&lt;", ">" becomes "&gt;", "&" becomes "&amp;", and
56240Sstevel@tonic-gatethe quote character becomes "&quot;".  In addition, the hexadecimal
56250Sstevel@tonic-gate0x8b and 0x9b characters, which some browsers incorrectly interpret
56260Sstevel@tonic-gateas the left and right angle-bracket characters, are replaced by their
56270Sstevel@tonic-gatenumeric character entities ("&#8249" and "&#8250;").  If you manually change
56280Sstevel@tonic-gatethe charset, either by calling the charset() method explicitly or by
56290Sstevel@tonic-gatepassing a -charset argument to header(), then B<all> characters will
56300Sstevel@tonic-gatebe replaced by their numeric entities, since CGI.pm has no lookup
56310Sstevel@tonic-gatetable for all the possible encodings.
56320Sstevel@tonic-gate
56330Sstevel@tonic-gateThe automatic escaping does not apply to other shortcuts, such as
56340Sstevel@tonic-gateh1().  You should call escapeHTML() yourself on untrusted data in
56350Sstevel@tonic-gateorder to protect your pages against nasty tricks that people may enter
56360Sstevel@tonic-gateinto guestbooks, etc..  To change the character set, use charset().
56370Sstevel@tonic-gateTo turn autoescaping off completely, use autoEscape(0):
56380Sstevel@tonic-gate
56390Sstevel@tonic-gate=over 4
56400Sstevel@tonic-gate
56410Sstevel@tonic-gate=item $charset = charset([$charset]);
56420Sstevel@tonic-gate
56430Sstevel@tonic-gateGet or set the current character set.
56440Sstevel@tonic-gate
56450Sstevel@tonic-gate=item $flag = autoEscape([$flag]);
56460Sstevel@tonic-gate
56470Sstevel@tonic-gateGet or set the value of the autoescape flag.
56480Sstevel@tonic-gate
56490Sstevel@tonic-gate=back
56500Sstevel@tonic-gate
56510Sstevel@tonic-gate=head2 PRETTY-PRINTING HTML
56520Sstevel@tonic-gate
56530Sstevel@tonic-gateBy default, all the HTML produced by these functions comes out as one
56540Sstevel@tonic-gatelong line without carriage returns or indentation. This is yuck, but
56550Sstevel@tonic-gateit does reduce the size of the documents by 10-20%.  To get
56560Sstevel@tonic-gatepretty-printed output, please use L<CGI::Pretty>, a subclass
56570Sstevel@tonic-gatecontributed by Brian Paulsen.
56580Sstevel@tonic-gate
56590Sstevel@tonic-gate=head1 CREATING FILL-OUT FORMS:
56600Sstevel@tonic-gate
56610Sstevel@tonic-gateI<General note>  The various form-creating methods all return strings
56620Sstevel@tonic-gateto the caller, containing the tag or tags that will create the requested
56630Sstevel@tonic-gateform element.  You are responsible for actually printing out these strings.
56640Sstevel@tonic-gateIt's set up this way so that you can place formatting tags
56650Sstevel@tonic-gatearound the form elements.
56660Sstevel@tonic-gate
56670Sstevel@tonic-gateI<Another note> The default values that you specify for the forms are only
56680Sstevel@tonic-gateused the B<first> time the script is invoked (when there is no query
56690Sstevel@tonic-gatestring).  On subsequent invocations of the script (when there is a query
56700Sstevel@tonic-gatestring), the former values are used even if they are blank.
56710Sstevel@tonic-gate
56720Sstevel@tonic-gateIf you want to change the value of a field from its previous value, you have two
56730Sstevel@tonic-gatechoices:
56740Sstevel@tonic-gate
56750Sstevel@tonic-gate(1) call the param() method to set it.
56760Sstevel@tonic-gate
56770Sstevel@tonic-gate(2) use the -override (alias -force) parameter (a new feature in version 2.15).
56780Sstevel@tonic-gateThis forces the default value to be used, regardless of the previous value:
56790Sstevel@tonic-gate
5680667Sps156622   print textfield(-name=>'field_name',
56810Sstevel@tonic-gate			   -default=>'starting value',
56820Sstevel@tonic-gate			   -override=>1,
56830Sstevel@tonic-gate			   -size=>50,
56840Sstevel@tonic-gate			   -maxlength=>80);
56850Sstevel@tonic-gate
56860Sstevel@tonic-gateI<Yet another note> By default, the text and labels of form elements are
56870Sstevel@tonic-gateescaped according to HTML rules.  This means that you can safely use
56880Sstevel@tonic-gate"<CLICK ME>" as the label for a button.  However, it also interferes with
56890Sstevel@tonic-gateyour ability to incorporate special HTML character sequences, such as &Aacute;,
56900Sstevel@tonic-gateinto your fields.  If you wish to turn off automatic escaping, call the
56910Sstevel@tonic-gateautoEscape() method with a false value immediately after creating the CGI object:
56920Sstevel@tonic-gate
56930Sstevel@tonic-gate   $query = new CGI;
5694667Sps156622   autoEscape(undef);
5695667Sps156622
5696667Sps156622I<A Lurking Trap!> Some of the form-element generating methods return
5697667Sps156622multiple tags.  In a scalar context, the tags will be concatenated
5698667Sps156622together with spaces, or whatever is the current value of the $"
5699667Sps156622global.  In a list context, the methods will return a list of
5700667Sps156622elements, allowing you to modify them if you wish.  Usually you will
5701667Sps156622not notice this behavior, but beware of this:
5702667Sps156622
5703667Sps156622    printf("%s\n",end_form())
5704667Sps156622
5705667Sps156622end_form() produces several tags, and only the first of them will be
5706667Sps156622printed because the format only expects one value.
5707667Sps156622
5708667Sps156622<p>
5709667Sps156622
57100Sstevel@tonic-gate
57110Sstevel@tonic-gate=head2 CREATING AN ISINDEX TAG
57120Sstevel@tonic-gate
5713667Sps156622   print isindex(-action=>$action);
57140Sstevel@tonic-gate
57150Sstevel@tonic-gate	 -or-
57160Sstevel@tonic-gate
5717667Sps156622   print isindex($action);
57180Sstevel@tonic-gate
57190Sstevel@tonic-gatePrints out an <isindex> tag.  Not very exciting.  The parameter
57200Sstevel@tonic-gate-action specifies the URL of the script to process the query.  The
57210Sstevel@tonic-gatedefault is to process the query with the current script.
57220Sstevel@tonic-gate
57230Sstevel@tonic-gate=head2 STARTING AND ENDING A FORM
57240Sstevel@tonic-gate
5725667Sps156622    print start_form(-method=>$method,
5726667Sps156622		    -action=>$action,
5727667Sps156622		    -enctype=>$encoding);
57280Sstevel@tonic-gate      <... various form stuff ...>
5729667Sps156622    print endform;
57300Sstevel@tonic-gate
57310Sstevel@tonic-gate	-or-
57320Sstevel@tonic-gate
5733667Sps156622    print start_form($method,$action,$encoding);
57340Sstevel@tonic-gate      <... various form stuff ...>
5735667Sps156622    print endform;
57360Sstevel@tonic-gate
57370Sstevel@tonic-gatestart_form() will return a <form> tag with the optional method,
57380Sstevel@tonic-gateaction and form encoding that you specify.  The defaults are:
57390Sstevel@tonic-gate
57400Sstevel@tonic-gate    method: POST
57410Sstevel@tonic-gate    action: this script
57420Sstevel@tonic-gate    enctype: application/x-www-form-urlencoded
57430Sstevel@tonic-gate
57440Sstevel@tonic-gateendform() returns the closing </form> tag.
57450Sstevel@tonic-gate
57460Sstevel@tonic-gateStart_form()'s enctype argument tells the browser how to package the various
57470Sstevel@tonic-gatefields of the form before sending the form to the server.  Two
57480Sstevel@tonic-gatevalues are possible:
57490Sstevel@tonic-gate
57500Sstevel@tonic-gateB<Note:> This method was previously named startform(), and startform()
57510Sstevel@tonic-gateis still recognized as an alias.
57520Sstevel@tonic-gate
57530Sstevel@tonic-gate=over 4
57540Sstevel@tonic-gate
57550Sstevel@tonic-gate=item B<application/x-www-form-urlencoded>
57560Sstevel@tonic-gate
57570Sstevel@tonic-gateThis is the older type of encoding used by all browsers prior to
57580Sstevel@tonic-gateNetscape 2.0.  It is compatible with many CGI scripts and is
57590Sstevel@tonic-gatesuitable for short fields containing text data.  For your
57600Sstevel@tonic-gateconvenience, CGI.pm stores the name of this encoding
57610Sstevel@tonic-gatetype in B<&CGI::URL_ENCODED>.
57620Sstevel@tonic-gate
57630Sstevel@tonic-gate=item B<multipart/form-data>
57640Sstevel@tonic-gate
57650Sstevel@tonic-gateThis is the newer type of encoding introduced by Netscape 2.0.
57660Sstevel@tonic-gateIt is suitable for forms that contain very large fields or that
57670Sstevel@tonic-gateare intended for transferring binary data.  Most importantly,
57680Sstevel@tonic-gateit enables the "file upload" feature of Netscape 2.0 forms.  For
57690Sstevel@tonic-gateyour convenience, CGI.pm stores the name of this encoding type
57700Sstevel@tonic-gatein B<&CGI::MULTIPART>
57710Sstevel@tonic-gate
57720Sstevel@tonic-gateForms that use this type of encoding are not easily interpreted
57730Sstevel@tonic-gateby CGI scripts unless they use CGI.pm or another library designed
57740Sstevel@tonic-gateto handle them.
57750Sstevel@tonic-gate
5776667Sps156622If XHTML is activated (the default), then forms will be automatically
5777667Sps156622created using this type of encoding.
5778667Sps156622
57790Sstevel@tonic-gate=back
57800Sstevel@tonic-gate
57810Sstevel@tonic-gateFor compatibility, the start_form() method uses the older form of
57820Sstevel@tonic-gateencoding by default.  If you want to use the newer form of encoding
57830Sstevel@tonic-gateby default, you can call B<start_multipart_form()> instead of
57840Sstevel@tonic-gateB<start_form()>.
57850Sstevel@tonic-gate
57860Sstevel@tonic-gateJAVASCRIPTING: The B<-name> and B<-onSubmit> parameters are provided
57870Sstevel@tonic-gatefor use with JavaScript.  The -name parameter gives the
57880Sstevel@tonic-gateform a name so that it can be identified and manipulated by
57890Sstevel@tonic-gateJavaScript functions.  -onSubmit should point to a JavaScript
57900Sstevel@tonic-gatefunction that will be executed just before the form is submitted to your
57910Sstevel@tonic-gateserver.  You can use this opportunity to check the contents of the form
57920Sstevel@tonic-gatefor consistency and completeness.  If you find something wrong, you
57930Sstevel@tonic-gatecan put up an alert box or maybe fix things up yourself.  You can
57940Sstevel@tonic-gateabort the submission by returning false from this function.
57950Sstevel@tonic-gate
57960Sstevel@tonic-gateUsually the bulk of JavaScript functions are defined in a <script>
57970Sstevel@tonic-gateblock in the HTML header and -onSubmit points to one of these function
57980Sstevel@tonic-gatecall.  See start_html() for details.
57990Sstevel@tonic-gate
5800667Sps156622=head2 FORM ELEMENTS
5801667Sps156622
5802667Sps156622After starting a form, you will typically create one or more
5803667Sps156622textfields, popup menus, radio groups and other form elements.  Each
5804667Sps156622of these elements takes a standard set of named arguments.  Some
5805667Sps156622elements also have optional arguments.  The standard arguments are as
5806667Sps156622follows:
5807667Sps156622
5808667Sps156622=over 4
5809667Sps156622
5810667Sps156622=item B<-name>
5811667Sps156622
5812667Sps156622The name of the field. After submission this name can be used to
5813667Sps156622retrieve the field's value using the param() method.
5814667Sps156622
5815667Sps156622=item B<-value>, B<-values>
5816667Sps156622
5817667Sps156622The initial value of the field which will be returned to the script
5818667Sps156622after form submission.  Some form elements, such as text fields, take
5819667Sps156622a single scalar -value argument. Others, such as popup menus, take a
5820667Sps156622reference to an array of values. The two arguments are synonyms.
5821667Sps156622
5822667Sps156622=item B<-tabindex>
5823667Sps156622
5824667Sps156622A numeric value that sets the order in which the form element receives
5825667Sps156622focus when the user presses the tab key. Elements with lower values
5826667Sps156622receive focus first.
5827667Sps156622
5828667Sps156622=item B<-id>
5829667Sps156622
5830667Sps156622A string identifier that can be used to identify this element to
5831667Sps156622JavaScript and DHTML.
5832667Sps156622
5833667Sps156622=item B<-override>
5834667Sps156622
5835667Sps156622A boolean, which, if true, forces the element to take on the value
5836667Sps156622specified by B<-value>, overriding the sticky behavior described
5837667Sps156622earlier for the B<-no_sticky> pragma.
5838667Sps156622
5839667Sps156622=item B<-onChange>, B<-onFocus>, B<-onBlur>, B<-onMouseOver>, B<-onMouseOut>, B<-onSelect>
5840667Sps156622
5841667Sps156622These are used to assign JavaScript event handlers. See the
5842667Sps156622JavaScripting section for more details.
5843667Sps156622
5844667Sps156622=back
5845667Sps156622
5846667Sps156622Other common arguments are described in the next section. In addition
5847667Sps156622to these, all attributes described in the HTML specifications are
5848667Sps156622supported.
5849667Sps156622
58500Sstevel@tonic-gate=head2 CREATING A TEXT FIELD
58510Sstevel@tonic-gate
5852667Sps156622    print textfield(-name=>'field_name',
5853667Sps156622		    -value=>'starting value',
5854667Sps156622		    -size=>50,
5855667Sps156622		    -maxlength=>80);
58560Sstevel@tonic-gate	-or-
58570Sstevel@tonic-gate
5858667Sps156622    print textfield('field_name','starting value',50,80);
5859667Sps156622
5860667Sps156622textfield() will return a text input field.
58610Sstevel@tonic-gate
58620Sstevel@tonic-gate=over 4
58630Sstevel@tonic-gate
58640Sstevel@tonic-gate=item B<Parameters>
58650Sstevel@tonic-gate
58660Sstevel@tonic-gate=item 1.
58670Sstevel@tonic-gate
5868667Sps156622The first parameter is the required name for the field (-name).
58690Sstevel@tonic-gate
58700Sstevel@tonic-gate=item 2.
58710Sstevel@tonic-gate
58720Sstevel@tonic-gateThe optional second parameter is the default starting value for the field
5873667Sps156622contents (-value, formerly known as -default).
58740Sstevel@tonic-gate
58750Sstevel@tonic-gate=item 3.
58760Sstevel@tonic-gate
58770Sstevel@tonic-gateThe optional third parameter is the size of the field in
58780Sstevel@tonic-gate      characters (-size).
58790Sstevel@tonic-gate
58800Sstevel@tonic-gate=item 4.
58810Sstevel@tonic-gate
58820Sstevel@tonic-gateThe optional fourth parameter is the maximum number of characters the
58830Sstevel@tonic-gate      field will accept (-maxlength).
58840Sstevel@tonic-gate
58850Sstevel@tonic-gate=back
58860Sstevel@tonic-gate
58870Sstevel@tonic-gateAs with all these methods, the field will be initialized with its
58880Sstevel@tonic-gateprevious contents from earlier invocations of the script.
58890Sstevel@tonic-gateWhen the form is processed, the value of the text field can be
58900Sstevel@tonic-gateretrieved with:
58910Sstevel@tonic-gate
5892667Sps156622       $value = param('foo');
58930Sstevel@tonic-gate
58940Sstevel@tonic-gateIf you want to reset it from its initial value after the script has been
58950Sstevel@tonic-gatecalled once, you can do so like this:
58960Sstevel@tonic-gate
5897667Sps156622       param('foo',"I'm taking over this value!");
58980Sstevel@tonic-gate
58990Sstevel@tonic-gate=head2 CREATING A BIG TEXT FIELD
59000Sstevel@tonic-gate
5901667Sps156622   print textarea(-name=>'foo',
59020Sstevel@tonic-gate			  -default=>'starting value',
59030Sstevel@tonic-gate			  -rows=>10,
59040Sstevel@tonic-gate			  -columns=>50);
59050Sstevel@tonic-gate
59060Sstevel@tonic-gate	-or
59070Sstevel@tonic-gate
5908667Sps156622   print textarea('foo','starting value',10,50);
59090Sstevel@tonic-gate
59100Sstevel@tonic-gatetextarea() is just like textfield, but it allows you to specify
59110Sstevel@tonic-gaterows and columns for a multiline text entry box.  You can provide
59120Sstevel@tonic-gatea starting value for the field, which can be long and contain
59130Sstevel@tonic-gatemultiple lines.
59140Sstevel@tonic-gate
59150Sstevel@tonic-gate=head2 CREATING A PASSWORD FIELD
59160Sstevel@tonic-gate
5917667Sps156622   print password_field(-name=>'secret',
59180Sstevel@tonic-gate				-value=>'starting value',
59190Sstevel@tonic-gate				-size=>50,
59200Sstevel@tonic-gate				-maxlength=>80);
59210Sstevel@tonic-gate	-or-
59220Sstevel@tonic-gate
5923667Sps156622   print password_field('secret','starting value',50,80);
59240Sstevel@tonic-gate
59250Sstevel@tonic-gatepassword_field() is identical to textfield(), except that its contents
59260Sstevel@tonic-gatewill be starred out on the web page.
59270Sstevel@tonic-gate
59280Sstevel@tonic-gate=head2 CREATING A FILE UPLOAD FIELD
59290Sstevel@tonic-gate
5930667Sps156622    print filefield(-name=>'uploaded_file',
59310Sstevel@tonic-gate			    -default=>'starting value',
59320Sstevel@tonic-gate			    -size=>50,
59330Sstevel@tonic-gate			    -maxlength=>80);
59340Sstevel@tonic-gate	-or-
59350Sstevel@tonic-gate
5936667Sps156622    print filefield('uploaded_file','starting value',50,80);
59370Sstevel@tonic-gate
59380Sstevel@tonic-gatefilefield() will return a file upload field for Netscape 2.0 browsers.
59390Sstevel@tonic-gateIn order to take full advantage of this I<you must use the new
59400Sstevel@tonic-gatemultipart encoding scheme> for the form.  You can do this either
59410Sstevel@tonic-gateby calling B<start_form()> with an encoding type of B<&CGI::MULTIPART>,
59420Sstevel@tonic-gateor by calling the new method B<start_multipart_form()> instead of
59430Sstevel@tonic-gatevanilla B<start_form()>.
59440Sstevel@tonic-gate
59450Sstevel@tonic-gate=over 4
59460Sstevel@tonic-gate
59470Sstevel@tonic-gate=item B<Parameters>
59480Sstevel@tonic-gate
59490Sstevel@tonic-gate=item 1.
59500Sstevel@tonic-gate
59510Sstevel@tonic-gateThe first parameter is the required name for the field (-name).
59520Sstevel@tonic-gate
59530Sstevel@tonic-gate=item 2.
59540Sstevel@tonic-gate
59550Sstevel@tonic-gateThe optional second parameter is the starting value for the field contents
59560Sstevel@tonic-gateto be used as the default file name (-default).
59570Sstevel@tonic-gate
59580Sstevel@tonic-gateFor security reasons, browsers don't pay any attention to this field,
59590Sstevel@tonic-gateand so the starting value will always be blank.  Worse, the field
59600Sstevel@tonic-gateloses its "sticky" behavior and forgets its previous contents.  The
59610Sstevel@tonic-gatestarting value field is called for in the HTML specification, however,
59620Sstevel@tonic-gateand possibly some browser will eventually provide support for it.
59630Sstevel@tonic-gate
59640Sstevel@tonic-gate=item 3.
59650Sstevel@tonic-gate
59660Sstevel@tonic-gateThe optional third parameter is the size of the field in
59670Sstevel@tonic-gatecharacters (-size).
59680Sstevel@tonic-gate
59690Sstevel@tonic-gate=item 4.
59700Sstevel@tonic-gate
59710Sstevel@tonic-gateThe optional fourth parameter is the maximum number of characters the
59720Sstevel@tonic-gatefield will accept (-maxlength).
59730Sstevel@tonic-gate
59740Sstevel@tonic-gate=back
59750Sstevel@tonic-gate
59760Sstevel@tonic-gateWhen the form is processed, you can retrieve the entered filename
59770Sstevel@tonic-gateby calling param():
59780Sstevel@tonic-gate
5979667Sps156622       $filename = param('uploaded_file');
59800Sstevel@tonic-gate
59810Sstevel@tonic-gateDifferent browsers will return slightly different things for the
59820Sstevel@tonic-gatename.  Some browsers return the filename only.  Others return the full
59830Sstevel@tonic-gatepath to the file, using the path conventions of the user's machine.
59840Sstevel@tonic-gateRegardless, the name returned is always the name of the file on the
59850Sstevel@tonic-gateI<user's> machine, and is unrelated to the name of the temporary file
59860Sstevel@tonic-gatethat CGI.pm creates during upload spooling (see below).
59870Sstevel@tonic-gate
59880Sstevel@tonic-gateThe filename returned is also a file handle.  You can read the contents
59890Sstevel@tonic-gateof the file using standard Perl file reading calls:
59900Sstevel@tonic-gate
59910Sstevel@tonic-gate	# Read a text file and print it out
59920Sstevel@tonic-gate	while (<$filename>) {
59930Sstevel@tonic-gate	   print;
59940Sstevel@tonic-gate	}
59950Sstevel@tonic-gate
59960Sstevel@tonic-gate	# Copy a binary file to somewhere safe
59970Sstevel@tonic-gate	open (OUTFILE,">>/usr/local/web/users/feedback");
59980Sstevel@tonic-gate	while ($bytesread=read($filename,$buffer,1024)) {
59990Sstevel@tonic-gate	   print OUTFILE $buffer;
60000Sstevel@tonic-gate	}
60010Sstevel@tonic-gate
60020Sstevel@tonic-gateHowever, there are problems with the dual nature of the upload fields.
60030Sstevel@tonic-gateIf you C<use strict>, then Perl will complain when you try to use a
60040Sstevel@tonic-gatestring as a filehandle.  You can get around this by placing the file
60050Sstevel@tonic-gatereading code in a block containing the C<no strict> pragma.  More
60060Sstevel@tonic-gateseriously, it is possible for the remote user to type garbage into the
60070Sstevel@tonic-gateupload field, in which case what you get from param() is not a
60080Sstevel@tonic-gatefilehandle at all, but a string.
60090Sstevel@tonic-gate
60100Sstevel@tonic-gateTo be safe, use the I<upload()> function (new in version 2.47).  When
60110Sstevel@tonic-gatecalled with the name of an upload field, I<upload()> returns a
60120Sstevel@tonic-gatefilehandle, or undef if the parameter is not a valid filehandle.
60130Sstevel@tonic-gate
6014667Sps156622     $fh = upload('uploaded_file');
60150Sstevel@tonic-gate     while (<$fh>) {
60160Sstevel@tonic-gate	   print;
60170Sstevel@tonic-gate     }
60180Sstevel@tonic-gate
6019667Sps156622In an list context, upload() will return an array of filehandles.
60200Sstevel@tonic-gateThis makes it possible to create forms that use the same name for
60210Sstevel@tonic-gatemultiple upload fields.
60220Sstevel@tonic-gate
60230Sstevel@tonic-gateThis is the recommended idiom.
60240Sstevel@tonic-gate
6025*6287Sps156622For robust code, consider reseting the file handle position to beginning of the
6026*6287Sps156622file. Inside of larger frameworks, other code may have already used the query
6027*6287Sps156622object and changed the filehandle postion:
6028*6287Sps156622
6029*6287Sps156622  seek($fh,0,0); # reset postion to beginning of file.
6030*6287Sps156622
60310Sstevel@tonic-gateWhen a file is uploaded the browser usually sends along some
60320Sstevel@tonic-gateinformation along with it in the format of headers.  The information
60330Sstevel@tonic-gateusually includes the MIME content type.  Future browsers may send
60340Sstevel@tonic-gateother information as well (such as modification date and size). To
60350Sstevel@tonic-gateretrieve this information, call uploadInfo().  It returns a reference to
60360Sstevel@tonic-gatean associative array containing all the document headers.
60370Sstevel@tonic-gate
6038667Sps156622       $filename = param('uploaded_file');
6039667Sps156622       $type = uploadInfo($filename)->{'Content-Type'};
60400Sstevel@tonic-gate       unless ($type eq 'text/html') {
60410Sstevel@tonic-gate	  die "HTML FILES ONLY!";
60420Sstevel@tonic-gate       }
60430Sstevel@tonic-gate
60440Sstevel@tonic-gateIf you are using a machine that recognizes "text" and "binary" data
60450Sstevel@tonic-gatemodes, be sure to understand when and how to use them (see the Camel book).
60460Sstevel@tonic-gateOtherwise you may find that binary files are corrupted during file
60470Sstevel@tonic-gateuploads.
60480Sstevel@tonic-gate
60490Sstevel@tonic-gateThere are occasionally problems involving parsing the uploaded file.
60500Sstevel@tonic-gateThis usually happens when the user presses "Stop" before the upload is
60510Sstevel@tonic-gatefinished.  In this case, CGI.pm will return undef for the name of the
60520Sstevel@tonic-gateuploaded file and set I<cgi_error()> to the string "400 Bad request
60530Sstevel@tonic-gate(malformed multipart POST)".  This error message is designed so that
60540Sstevel@tonic-gateyou can incorporate it into a status code to be sent to the browser.
60550Sstevel@tonic-gateExample:
60560Sstevel@tonic-gate
6057667Sps156622   $file = upload('uploaded_file');
6058667Sps156622   if (!$file && cgi_error) {
6059667Sps156622      print header(-status=>cgi_error);
60600Sstevel@tonic-gate      exit 0;
60610Sstevel@tonic-gate   }
60620Sstevel@tonic-gate
60630Sstevel@tonic-gateYou are free to create a custom HTML page to complain about the error,
60640Sstevel@tonic-gateif you wish.
60650Sstevel@tonic-gate
60660Sstevel@tonic-gateYou can set up a callback that will be called whenever a file upload
60670Sstevel@tonic-gateis being read during the form processing. This is much like the
60680Sstevel@tonic-gateUPLOAD_HOOK facility available in Apache::Request, with the exception
60690Sstevel@tonic-gatethat the first argument to the callback is an Apache::Upload object,
60700Sstevel@tonic-gatehere it's the remote filename.
60710Sstevel@tonic-gate
6072*6287Sps156622 $q = CGI->new(\&hook [,$data [,$use_tempfile]]);
60730Sstevel@tonic-gate
60740Sstevel@tonic-gate sub hook
60750Sstevel@tonic-gate {
60760Sstevel@tonic-gate        my ($filename, $buffer, $bytes_read, $data) = @_;
60770Sstevel@tonic-gate        print  "Read $bytes_read bytes of $filename\n";
60780Sstevel@tonic-gate }
60790Sstevel@tonic-gate
6080*6287Sps156622The $data field is optional; it lets you pass configuration
6081*6287Sps156622information (e.g. a database handle) to your hook callback.
6082*6287Sps156622
6083*6287Sps156622The $use_tempfile field is a flag that lets you turn on and off
6084*6287Sps156622CGI.pm's use of a temporary disk-based file during file upload. If you
6085*6287Sps156622set this to a FALSE value (default true) then param('uploaded_file')
6086*6287Sps156622will no longer work, and the only way to get at the uploaded data is
6087*6287Sps156622via the hook you provide.
6088*6287Sps156622
60890Sstevel@tonic-gateIf using the function-oriented interface, call the CGI::upload_hook()
60900Sstevel@tonic-gatemethod before calling param() or any other CGI functions:
60910Sstevel@tonic-gate
6092*6287Sps156622  CGI::upload_hook(\&hook [,$data [,$use_tempfile]]);
60930Sstevel@tonic-gate
60940Sstevel@tonic-gateThis method is not exported by default.  You will have to import it
60950Sstevel@tonic-gateexplicitly if you wish to use it without the CGI:: prefix.
60960Sstevel@tonic-gate
60970Sstevel@tonic-gateIf you are using CGI.pm on a Windows platform and find that binary
60980Sstevel@tonic-gatefiles get slightly larger when uploaded but that text files remain the
60990Sstevel@tonic-gatesame, then you have forgotten to activate binary mode on the output
61000Sstevel@tonic-gatefilehandle.  Be sure to call binmode() on any handle that you create
61010Sstevel@tonic-gateto write the uploaded file to disk.
61020Sstevel@tonic-gate
61030Sstevel@tonic-gateJAVASCRIPTING: The B<-onChange>, B<-onFocus>, B<-onBlur>,
61040Sstevel@tonic-gateB<-onMouseOver>, B<-onMouseOut> and B<-onSelect> parameters are
61050Sstevel@tonic-gaterecognized.  See textfield() for details.
61060Sstevel@tonic-gate
61070Sstevel@tonic-gate=head2 CREATING A POPUP MENU
61080Sstevel@tonic-gate
6109667Sps156622   print popup_menu('menu_name',
61100Sstevel@tonic-gate			    ['eenie','meenie','minie'],
61110Sstevel@tonic-gate			    'meenie');
61120Sstevel@tonic-gate
61130Sstevel@tonic-gate      -or-
61140Sstevel@tonic-gate
61150Sstevel@tonic-gate   %labels = ('eenie'=>'your first choice',
61160Sstevel@tonic-gate	      'meenie'=>'your second choice',
61170Sstevel@tonic-gate	      'minie'=>'your third choice');
61180Sstevel@tonic-gate   %attributes = ('eenie'=>{'class'=>'class of first choice'});
6119667Sps156622   print popup_menu('menu_name',
61200Sstevel@tonic-gate			    ['eenie','meenie','minie'],
61210Sstevel@tonic-gate          'meenie',\%labels,\%attributes);
61220Sstevel@tonic-gate
61230Sstevel@tonic-gate	-or (named parameter style)-
61240Sstevel@tonic-gate
6125667Sps156622   print popup_menu(-name=>'menu_name',
61260Sstevel@tonic-gate			    -values=>['eenie','meenie','minie'],
61270Sstevel@tonic-gate			    -default=>'meenie',
61280Sstevel@tonic-gate          -labels=>\%labels,
61290Sstevel@tonic-gate          -attributes=>\%attributes);
61300Sstevel@tonic-gate
61310Sstevel@tonic-gatepopup_menu() creates a menu.
61320Sstevel@tonic-gate
61330Sstevel@tonic-gate=over 4
61340Sstevel@tonic-gate
61350Sstevel@tonic-gate=item 1.
61360Sstevel@tonic-gate
61370Sstevel@tonic-gateThe required first argument is the menu's name (-name).
61380Sstevel@tonic-gate
61390Sstevel@tonic-gate=item 2.
61400Sstevel@tonic-gate
61410Sstevel@tonic-gateThe required second argument (-values) is an array B<reference>
61420Sstevel@tonic-gatecontaining the list of menu items in the menu.  You can pass the
61430Sstevel@tonic-gatemethod an anonymous array, as shown in the example, or a reference to
61440Sstevel@tonic-gatea named array, such as "\@foo".
61450Sstevel@tonic-gate
61460Sstevel@tonic-gate=item 3.
61470Sstevel@tonic-gate
61480Sstevel@tonic-gateThe optional third parameter (-default) is the name of the default
61490Sstevel@tonic-gatemenu choice.  If not specified, the first item will be the default.
61500Sstevel@tonic-gateThe values of the previous choice will be maintained across queries.
61510Sstevel@tonic-gate
61520Sstevel@tonic-gate=item 4.
61530Sstevel@tonic-gate
61540Sstevel@tonic-gateThe optional fourth parameter (-labels) is provided for people who
61550Sstevel@tonic-gatewant to use different values for the user-visible label inside the
61560Sstevel@tonic-gatepopup menu and the value returned to your script.  It's a pointer to an
61570Sstevel@tonic-gateassociative array relating menu values to user-visible labels.  If you
61580Sstevel@tonic-gateleave this parameter blank, the menu values will be displayed by
61590Sstevel@tonic-gatedefault.  (You can also leave a label undefined if you want to).
61600Sstevel@tonic-gate
61610Sstevel@tonic-gate=item 5.
61620Sstevel@tonic-gate
61630Sstevel@tonic-gateThe optional fifth parameter (-attributes) is provided to assign
61640Sstevel@tonic-gateany of the common HTML attributes to an individual menu item. It's
61650Sstevel@tonic-gatea pointer to an associative array relating menu values to another
61660Sstevel@tonic-gateassociative array with the attribute's name as the key and the
61670Sstevel@tonic-gateattribute's value as the value.
61680Sstevel@tonic-gate
61690Sstevel@tonic-gate=back
61700Sstevel@tonic-gate
61710Sstevel@tonic-gateWhen the form is processed, the selected value of the popup menu can
61720Sstevel@tonic-gatebe retrieved using:
61730Sstevel@tonic-gate
6174667Sps156622      $popup_menu_value = param('menu_name');
61750Sstevel@tonic-gate
61760Sstevel@tonic-gate=head2 CREATING AN OPTION GROUP
61770Sstevel@tonic-gate
61780Sstevel@tonic-gateNamed parameter style
61790Sstevel@tonic-gate
6180667Sps156622  print popup_menu(-name=>'menu_name',
61810Sstevel@tonic-gate                  -values=>[qw/eenie meenie minie/,
6182667Sps156622                            optgroup(-name=>'optgroup_name',
6183667Sps156622                                             -values => ['moe','catch'],
6184667Sps156622                                             -attributes=>{'catch'=>{'class'=>'red'}})],
61850Sstevel@tonic-gate                  -labels=>{'eenie'=>'one',
61860Sstevel@tonic-gate                            'meenie'=>'two',
61870Sstevel@tonic-gate                            'minie'=>'three'},
61880Sstevel@tonic-gate                  -default=>'meenie');
61890Sstevel@tonic-gate
61900Sstevel@tonic-gate  Old style
6191667Sps156622  print popup_menu('menu_name',
61920Sstevel@tonic-gate                  ['eenie','meenie','minie',
6193667Sps156622                   optgroup('optgroup_name', ['moe', 'catch'],
6194667Sps156622                                   {'catch'=>{'class'=>'red'}})],'meenie',
61950Sstevel@tonic-gate                  {'eenie'=>'one','meenie'=>'two','minie'=>'three'});
61960Sstevel@tonic-gate
6197667Sps156622optgroup() creates an option group within a popup menu.
61980Sstevel@tonic-gate
61990Sstevel@tonic-gate=over 4
62000Sstevel@tonic-gate
62010Sstevel@tonic-gate=item 1.
62020Sstevel@tonic-gate
62030Sstevel@tonic-gateThe required first argument (B<-name>) is the label attribute of the
62040Sstevel@tonic-gateoptgroup and is B<not> inserted in the parameter list of the query.
62050Sstevel@tonic-gate
62060Sstevel@tonic-gate=item 2.
62070Sstevel@tonic-gate
62080Sstevel@tonic-gateThe required second argument (B<-values>)  is an array reference
62090Sstevel@tonic-gatecontaining the list of menu items in the menu.  You can pass the
62100Sstevel@tonic-gatemethod an anonymous array, as shown in the example, or a reference
62110Sstevel@tonic-gateto a named array, such as \@foo.  If you pass a HASH reference,
62120Sstevel@tonic-gatethe keys will be used for the menu values, and the values will be
62130Sstevel@tonic-gateused for the menu labels (see -labels below).
62140Sstevel@tonic-gate
62150Sstevel@tonic-gate=item 3.
62160Sstevel@tonic-gate
62170Sstevel@tonic-gateThe optional third parameter (B<-labels>) allows you to pass a reference
62180Sstevel@tonic-gateto an associative array containing user-visible labels for one or more
62190Sstevel@tonic-gateof the menu items.  You can use this when you want the user to see one
62200Sstevel@tonic-gatemenu string, but have the browser return your program a different one.
62210Sstevel@tonic-gateIf you don't specify this, the value string will be used instead
62220Sstevel@tonic-gate("eenie", "meenie" and "minie" in this example).  This is equivalent
62230Sstevel@tonic-gateto using a hash reference for the -values parameter.
62240Sstevel@tonic-gate
62250Sstevel@tonic-gate=item 4.
62260Sstevel@tonic-gate
62270Sstevel@tonic-gateAn optional fourth parameter (B<-labeled>) can be set to a true value
62280Sstevel@tonic-gateand indicates that the values should be used as the label attribute
62290Sstevel@tonic-gatefor each option element within the optgroup.
62300Sstevel@tonic-gate
62310Sstevel@tonic-gate=item 5.
62320Sstevel@tonic-gate
62330Sstevel@tonic-gateAn optional fifth parameter (-novals) can be set to a true value and
6234*6287Sps156622indicates to suppress the val attribute in each option element within
62350Sstevel@tonic-gatethe optgroup.
62360Sstevel@tonic-gate
62370Sstevel@tonic-gateSee the discussion on optgroup at W3C
62380Sstevel@tonic-gate(http://www.w3.org/TR/REC-html40/interact/forms.html#edef-OPTGROUP)
62390Sstevel@tonic-gatefor details.
62400Sstevel@tonic-gate
62410Sstevel@tonic-gate=item 6.
62420Sstevel@tonic-gate
62430Sstevel@tonic-gateAn optional sixth parameter (-attributes) is provided to assign
62440Sstevel@tonic-gateany of the common HTML attributes to an individual menu item. It's
62450Sstevel@tonic-gatea pointer to an associative array relating menu values to another
62460Sstevel@tonic-gateassociative array with the attribute's name as the key and the
62470Sstevel@tonic-gateattribute's value as the value.
62480Sstevel@tonic-gate
62490Sstevel@tonic-gate=back
62500Sstevel@tonic-gate
62510Sstevel@tonic-gate=head2 CREATING A SCROLLING LIST
62520Sstevel@tonic-gate
6253667Sps156622   print scrolling_list('list_name',
62540Sstevel@tonic-gate				['eenie','meenie','minie','moe'],
62550Sstevel@tonic-gate        ['eenie','moe'],5,'true',{'moe'=>{'class'=>'red'}});
62560Sstevel@tonic-gate      -or-
62570Sstevel@tonic-gate
6258667Sps156622   print scrolling_list('list_name',
62590Sstevel@tonic-gate				['eenie','meenie','minie','moe'],
62600Sstevel@tonic-gate				['eenie','moe'],5,'true',
62610Sstevel@tonic-gate        \%labels,%attributes);
62620Sstevel@tonic-gate
62630Sstevel@tonic-gate	-or-
62640Sstevel@tonic-gate
6265667Sps156622   print scrolling_list(-name=>'list_name',
62660Sstevel@tonic-gate				-values=>['eenie','meenie','minie','moe'],
62670Sstevel@tonic-gate				-default=>['eenie','moe'],
62680Sstevel@tonic-gate				-size=>5,
62690Sstevel@tonic-gate				-multiple=>'true',
62700Sstevel@tonic-gate        -labels=>\%labels,
62710Sstevel@tonic-gate        -attributes=>\%attributes);
62720Sstevel@tonic-gate
62730Sstevel@tonic-gatescrolling_list() creates a scrolling list.
62740Sstevel@tonic-gate
62750Sstevel@tonic-gate=over 4
62760Sstevel@tonic-gate
62770Sstevel@tonic-gate=item B<Parameters:>
62780Sstevel@tonic-gate
62790Sstevel@tonic-gate=item 1.
62800Sstevel@tonic-gate
62810Sstevel@tonic-gateThe first and second arguments are the list name (-name) and values
62820Sstevel@tonic-gate(-values).  As in the popup menu, the second argument should be an
62830Sstevel@tonic-gatearray reference.
62840Sstevel@tonic-gate
62850Sstevel@tonic-gate=item 2.
62860Sstevel@tonic-gate
62870Sstevel@tonic-gateThe optional third argument (-default) can be either a reference to a
62880Sstevel@tonic-gatelist containing the values to be selected by default, or can be a
62890Sstevel@tonic-gatesingle value to select.  If this argument is missing or undefined,
62900Sstevel@tonic-gatethen nothing is selected when the list first appears.  In the named
62910Sstevel@tonic-gateparameter version, you can use the synonym "-defaults" for this
62920Sstevel@tonic-gateparameter.
62930Sstevel@tonic-gate
62940Sstevel@tonic-gate=item 3.
62950Sstevel@tonic-gate
62960Sstevel@tonic-gateThe optional fourth argument is the size of the list (-size).
62970Sstevel@tonic-gate
62980Sstevel@tonic-gate=item 4.
62990Sstevel@tonic-gate
63000Sstevel@tonic-gateThe optional fifth argument can be set to true to allow multiple
63010Sstevel@tonic-gatesimultaneous selections (-multiple).  Otherwise only one selection
63020Sstevel@tonic-gatewill be allowed at a time.
63030Sstevel@tonic-gate
63040Sstevel@tonic-gate=item 5.
63050Sstevel@tonic-gate
63060Sstevel@tonic-gateThe optional sixth argument is a pointer to an associative array
63070Sstevel@tonic-gatecontaining long user-visible labels for the list items (-labels).
63080Sstevel@tonic-gateIf not provided, the values will be displayed.
63090Sstevel@tonic-gate
63100Sstevel@tonic-gate=item 6.
63110Sstevel@tonic-gate
63120Sstevel@tonic-gateThe optional sixth parameter (-attributes) is provided to assign
63130Sstevel@tonic-gateany of the common HTML attributes to an individual menu item. It's
63140Sstevel@tonic-gatea pointer to an associative array relating menu values to another
63150Sstevel@tonic-gateassociative array with the attribute's name as the key and the
63160Sstevel@tonic-gateattribute's value as the value.
63170Sstevel@tonic-gate
63180Sstevel@tonic-gateWhen this form is processed, all selected list items will be returned as
63190Sstevel@tonic-gatea list under the parameter name 'list_name'.  The values of the
63200Sstevel@tonic-gateselected items can be retrieved with:
63210Sstevel@tonic-gate
6322667Sps156622      @selected = param('list_name');
63230Sstevel@tonic-gate
63240Sstevel@tonic-gate=back
63250Sstevel@tonic-gate
63260Sstevel@tonic-gate=head2 CREATING A GROUP OF RELATED CHECKBOXES
63270Sstevel@tonic-gate
6328667Sps156622   print checkbox_group(-name=>'group_name',
63290Sstevel@tonic-gate				-values=>['eenie','meenie','minie','moe'],
63300Sstevel@tonic-gate				-default=>['eenie','moe'],
63310Sstevel@tonic-gate				-linebreak=>'true',
6332*6287Sps156622                                -disabled => ['moe'],
63330Sstevel@tonic-gate        -labels=>\%labels,
63340Sstevel@tonic-gate        -attributes=>\%attributes);
63350Sstevel@tonic-gate
6336667Sps156622   print checkbox_group('group_name',
63370Sstevel@tonic-gate				['eenie','meenie','minie','moe'],
63380Sstevel@tonic-gate        ['eenie','moe'],'true',\%labels,
63390Sstevel@tonic-gate        {'moe'=>{'class'=>'red'}});
63400Sstevel@tonic-gate
63410Sstevel@tonic-gate   HTML3-COMPATIBLE BROWSERS ONLY:
63420Sstevel@tonic-gate
6343667Sps156622   print checkbox_group(-name=>'group_name',
63440Sstevel@tonic-gate				-values=>['eenie','meenie','minie','moe'],
63450Sstevel@tonic-gate				-rows=2,-columns=>2);
63460Sstevel@tonic-gate
63470Sstevel@tonic-gate
63480Sstevel@tonic-gatecheckbox_group() creates a list of checkboxes that are related
63490Sstevel@tonic-gateby the same name.
63500Sstevel@tonic-gate
63510Sstevel@tonic-gate=over 4
63520Sstevel@tonic-gate
63530Sstevel@tonic-gate=item B<Parameters:>
63540Sstevel@tonic-gate
63550Sstevel@tonic-gate=item 1.
63560Sstevel@tonic-gate
63570Sstevel@tonic-gateThe first and second arguments are the checkbox name and values,
63580Sstevel@tonic-gaterespectively (-name and -values).  As in the popup menu, the second
63590Sstevel@tonic-gateargument should be an array reference.  These values are used for the
63600Sstevel@tonic-gateuser-readable labels printed next to the checkboxes as well as for the
63610Sstevel@tonic-gatevalues passed to your script in the query string.
63620Sstevel@tonic-gate
63630Sstevel@tonic-gate=item 2.
63640Sstevel@tonic-gate
63650Sstevel@tonic-gateThe optional third argument (-default) can be either a reference to a
63660Sstevel@tonic-gatelist containing the values to be checked by default, or can be a
63670Sstevel@tonic-gatesingle value to checked.  If this argument is missing or undefined,
63680Sstevel@tonic-gatethen nothing is selected when the list first appears.
63690Sstevel@tonic-gate
63700Sstevel@tonic-gate=item 3.
63710Sstevel@tonic-gate
63720Sstevel@tonic-gateThe optional fourth argument (-linebreak) can be set to true to place
63730Sstevel@tonic-gateline breaks between the checkboxes so that they appear as a vertical
63740Sstevel@tonic-gatelist.  Otherwise, they will be strung together on a horizontal line.
63750Sstevel@tonic-gate
63760Sstevel@tonic-gate=back
63770Sstevel@tonic-gate
6378667Sps156622
6379667Sps156622The optional b<-labels> argument is a pointer to an associative array
6380667Sps156622relating the checkbox values to the user-visible labels that will be
6381667Sps156622printed next to them.  If not provided, the values will be used as the
6382667Sps156622default.
6383667Sps156622
6384667Sps156622
6385*6287Sps156622The optional parameters B<-rows>, and B<-columns> cause
6386*6287Sps156622checkbox_group() to return an HTML3 compatible table containing the
6387*6287Sps156622checkbox group formatted with the specified number of rows and
6388*6287Sps156622columns.  You can provide just the -columns parameter if you wish;
6389*6287Sps156622checkbox_group will calculate the correct number of rows for you.
6390*6287Sps156622
6391*6287Sps156622The option b<-disabled> takes an array of checkbox values and disables
6392*6287Sps156622them by greying them out (this may not be supported by all browsers).
6393667Sps156622
6394667Sps156622The optional B<-attributes> argument is provided to assign any of the
6395667Sps156622common HTML attributes to an individual menu item. It's a pointer to
6396667Sps156622an associative array relating menu values to another associative array
6397667Sps156622with the attribute's name as the key and the attribute's value as the
6398667Sps156622value.
6399667Sps156622
6400667Sps156622The optional B<-tabindex> argument can be used to control the order in which
6401667Sps156622radio buttons receive focus when the user presses the tab button.  If
6402667Sps156622passed a scalar numeric value, the first element in the group will
6403667Sps156622receive this tab index and subsequent elements will be incremented by
6404667Sps156622one.  If given a reference to an array of radio button values, then
6405667Sps156622the indexes will be jiggered so that the order specified in the array
6406667Sps156622will correspond to the tab order.  You can also pass a reference to a
6407667Sps156622hash in which the hash keys are the radio button values and the values
6408667Sps156622are the tab indexes of each button.  Examples:
6409667Sps156622
6410667Sps156622  -tabindex => 100    #  this group starts at index 100 and counts up
6411667Sps156622  -tabindex => ['moe','minie','eenie','meenie']  # tab in this order
6412667Sps156622  -tabindex => {meenie=>100,moe=>101,minie=>102,eenie=>200} # tab in this order
6413667Sps156622
6414*6287Sps156622The optional B<-labelattributes> argument will contain attributes
6415*6287Sps156622attached to the <label> element that surrounds each button.
6416*6287Sps156622
64170Sstevel@tonic-gateWhen the form is processed, all checked boxes will be returned as
64180Sstevel@tonic-gatea list under the parameter name 'group_name'.  The values of the
64190Sstevel@tonic-gate"on" checkboxes can be retrieved with:
64200Sstevel@tonic-gate
6421667Sps156622      @turned_on = param('group_name');
64220Sstevel@tonic-gate
64230Sstevel@tonic-gateThe value returned by checkbox_group() is actually an array of button
64240Sstevel@tonic-gateelements.  You can capture them and use them within tables, lists,
64250Sstevel@tonic-gateor in other creative ways:
64260Sstevel@tonic-gate
6427667Sps156622    @h = checkbox_group(-name=>'group_name',-values=>\@values);
64280Sstevel@tonic-gate    &use_in_creative_way(@h);
64290Sstevel@tonic-gate
64300Sstevel@tonic-gate=head2 CREATING A STANDALONE CHECKBOX
64310Sstevel@tonic-gate
6432667Sps156622    print checkbox(-name=>'checkbox_name',
64330Sstevel@tonic-gate			   -checked=>1,
64340Sstevel@tonic-gate			   -value=>'ON',
64350Sstevel@tonic-gate			   -label=>'CLICK ME');
64360Sstevel@tonic-gate
64370Sstevel@tonic-gate	-or-
64380Sstevel@tonic-gate
6439667Sps156622    print checkbox('checkbox_name','checked','ON','CLICK ME');
64400Sstevel@tonic-gate
64410Sstevel@tonic-gatecheckbox() is used to create an isolated checkbox that isn't logically
64420Sstevel@tonic-gaterelated to any others.
64430Sstevel@tonic-gate
64440Sstevel@tonic-gate=over 4
64450Sstevel@tonic-gate
64460Sstevel@tonic-gate=item B<Parameters:>
64470Sstevel@tonic-gate
64480Sstevel@tonic-gate=item 1.
64490Sstevel@tonic-gate
64500Sstevel@tonic-gateThe first parameter is the required name for the checkbox (-name).  It
64510Sstevel@tonic-gatewill also be used for the user-readable label printed next to the
64520Sstevel@tonic-gatecheckbox.
64530Sstevel@tonic-gate
64540Sstevel@tonic-gate=item 2.
64550Sstevel@tonic-gate
64560Sstevel@tonic-gateThe optional second parameter (-checked) specifies that the checkbox
64570Sstevel@tonic-gateis turned on by default.  Synonyms are -selected and -on.
64580Sstevel@tonic-gate
64590Sstevel@tonic-gate=item 3.
64600Sstevel@tonic-gate
64610Sstevel@tonic-gateThe optional third parameter (-value) specifies the value of the
64620Sstevel@tonic-gatecheckbox when it is checked.  If not provided, the word "on" is
64630Sstevel@tonic-gateassumed.
64640Sstevel@tonic-gate
64650Sstevel@tonic-gate=item 4.
64660Sstevel@tonic-gate
64670Sstevel@tonic-gateThe optional fourth parameter (-label) is the user-readable label to
64680Sstevel@tonic-gatebe attached to the checkbox.  If not provided, the checkbox name is
64690Sstevel@tonic-gateused.
64700Sstevel@tonic-gate
64710Sstevel@tonic-gate=back
64720Sstevel@tonic-gate
64730Sstevel@tonic-gateThe value of the checkbox can be retrieved using:
64740Sstevel@tonic-gate
6475667Sps156622    $turned_on = param('checkbox_name');
64760Sstevel@tonic-gate
64770Sstevel@tonic-gate=head2 CREATING A RADIO BUTTON GROUP
64780Sstevel@tonic-gate
6479667Sps156622   print radio_group(-name=>'group_name',
64800Sstevel@tonic-gate			     -values=>['eenie','meenie','minie'],
64810Sstevel@tonic-gate			     -default=>'meenie',
64820Sstevel@tonic-gate			     -linebreak=>'true',
64830Sstevel@tonic-gate           -labels=>\%labels,
64840Sstevel@tonic-gate           -attributes=>\%attributes);
64850Sstevel@tonic-gate
64860Sstevel@tonic-gate	-or-
64870Sstevel@tonic-gate
6488667Sps156622   print radio_group('group_name',['eenie','meenie','minie'],
64890Sstevel@tonic-gate            'meenie','true',\%labels,\%attributes);
64900Sstevel@tonic-gate
64910Sstevel@tonic-gate
64920Sstevel@tonic-gate   HTML3-COMPATIBLE BROWSERS ONLY:
64930Sstevel@tonic-gate
6494667Sps156622   print radio_group(-name=>'group_name',
64950Sstevel@tonic-gate			     -values=>['eenie','meenie','minie','moe'],
64960Sstevel@tonic-gate			     -rows=2,-columns=>2);
64970Sstevel@tonic-gate
64980Sstevel@tonic-gateradio_group() creates a set of logically-related radio buttons
64990Sstevel@tonic-gate(turning one member of the group on turns the others off)
65000Sstevel@tonic-gate
65010Sstevel@tonic-gate=over 4
65020Sstevel@tonic-gate
65030Sstevel@tonic-gate=item B<Parameters:>
65040Sstevel@tonic-gate
65050Sstevel@tonic-gate=item 1.
65060Sstevel@tonic-gate
65070Sstevel@tonic-gateThe first argument is the name of the group and is required (-name).
65080Sstevel@tonic-gate
65090Sstevel@tonic-gate=item 2.
65100Sstevel@tonic-gate
65110Sstevel@tonic-gateThe second argument (-values) is the list of values for the radio
65120Sstevel@tonic-gatebuttons.  The values and the labels that appear on the page are
65130Sstevel@tonic-gateidentical.  Pass an array I<reference> in the second argument, either
65140Sstevel@tonic-gateusing an anonymous array, as shown, or by referencing a named array as
65150Sstevel@tonic-gatein "\@foo".
65160Sstevel@tonic-gate
65170Sstevel@tonic-gate=item 3.
65180Sstevel@tonic-gate
65190Sstevel@tonic-gateThe optional third parameter (-default) is the name of the default
65200Sstevel@tonic-gatebutton to turn on. If not specified, the first item will be the
65210Sstevel@tonic-gatedefault.  You can provide a nonexistent button name, such as "-" to
65220Sstevel@tonic-gatestart up with no buttons selected.
65230Sstevel@tonic-gate
65240Sstevel@tonic-gate=item 4.
65250Sstevel@tonic-gate
65260Sstevel@tonic-gateThe optional fourth parameter (-linebreak) can be set to 'true' to put
65270Sstevel@tonic-gateline breaks between the buttons, creating a vertical list.
65280Sstevel@tonic-gate
65290Sstevel@tonic-gate=item 5.
65300Sstevel@tonic-gate
65310Sstevel@tonic-gateThe optional fifth parameter (-labels) is a pointer to an associative
65320Sstevel@tonic-gatearray relating the radio button values to user-visible labels to be
65330Sstevel@tonic-gateused in the display.  If not provided, the values themselves are
65340Sstevel@tonic-gatedisplayed.
65350Sstevel@tonic-gate
6536667Sps156622=back
6537667Sps156622
6538667Sps156622
6539667Sps156622All modern browsers can take advantage of the optional parameters
6540667Sps156622B<-rows>, and B<-columns>.  These parameters cause radio_group() to
6541667Sps156622return an HTML3 compatible table containing the radio group formatted
6542667Sps156622with the specified number of rows and columns.  You can provide just
6543667Sps156622the -columns parameter if you wish; radio_group will calculate the
6544667Sps156622correct number of rows for you.
65450Sstevel@tonic-gate
65460Sstevel@tonic-gateTo include row and column headings in the returned table, you
6547*6287Sps156622can use the B<-rowheaders> and B<-colheaders> parameters.  Both
65480Sstevel@tonic-gateof these accept a pointer to an array of headings to use.
65490Sstevel@tonic-gateThe headings are just decorative.  They don't reorganize the
65500Sstevel@tonic-gateinterpretation of the radio buttons -- they're still a single named
65510Sstevel@tonic-gateunit.
65520Sstevel@tonic-gate
6553667Sps156622The optional B<-tabindex> argument can be used to control the order in which
6554667Sps156622radio buttons receive focus when the user presses the tab button.  If
6555667Sps156622passed a scalar numeric value, the first element in the group will
6556667Sps156622receive this tab index and subsequent elements will be incremented by
6557667Sps156622one.  If given a reference to an array of radio button values, then
6558667Sps156622the indexes will be jiggered so that the order specified in the array
6559667Sps156622will correspond to the tab order.  You can also pass a reference to a
6560667Sps156622hash in which the hash keys are the radio button values and the values
6561667Sps156622are the tab indexes of each button.  Examples:
6562667Sps156622
6563667Sps156622  -tabindex => 100    #  this group starts at index 100 and counts up
6564667Sps156622  -tabindex => ['moe','minie','eenie','meenie']  # tab in this order
6565667Sps156622  -tabindex => {meenie=>100,moe=>101,minie=>102,eenie=>200} # tab in this order
6566667Sps156622
6567667Sps156622
6568667Sps156622The optional B<-attributes> argument is provided to assign any of the
6569667Sps156622common HTML attributes to an individual menu item. It's a pointer to
6570667Sps156622an associative array relating menu values to another associative array
6571667Sps156622with the attribute's name as the key and the attribute's value as the
6572667Sps156622value.
65730Sstevel@tonic-gate
6574*6287Sps156622The optional B<-labelattributes> argument will contain attributes
6575*6287Sps156622attached to the <label> element that surrounds each button.
6576*6287Sps156622
65770Sstevel@tonic-gateWhen the form is processed, the selected radio button can
65780Sstevel@tonic-gatebe retrieved using:
65790Sstevel@tonic-gate
6580667Sps156622      $which_radio_button = param('group_name');
65810Sstevel@tonic-gate
65820Sstevel@tonic-gateThe value returned by radio_group() is actually an array of button
65830Sstevel@tonic-gateelements.  You can capture them and use them within tables, lists,
65840Sstevel@tonic-gateor in other creative ways:
65850Sstevel@tonic-gate
6586667Sps156622    @h = radio_group(-name=>'group_name',-values=>\@values);
65870Sstevel@tonic-gate    &use_in_creative_way(@h);
65880Sstevel@tonic-gate
65890Sstevel@tonic-gate=head2 CREATING A SUBMIT BUTTON
65900Sstevel@tonic-gate
6591667Sps156622   print submit(-name=>'button_name',
65920Sstevel@tonic-gate			-value=>'value');
65930Sstevel@tonic-gate
65940Sstevel@tonic-gate	-or-
65950Sstevel@tonic-gate
6596667Sps156622   print submit('button_name','value');
65970Sstevel@tonic-gate
65980Sstevel@tonic-gatesubmit() will create the query submission button.  Every form
65990Sstevel@tonic-gateshould have one of these.
66000Sstevel@tonic-gate
66010Sstevel@tonic-gate=over 4
66020Sstevel@tonic-gate
66030Sstevel@tonic-gate=item B<Parameters:>
66040Sstevel@tonic-gate
66050Sstevel@tonic-gate=item 1.
66060Sstevel@tonic-gate
66070Sstevel@tonic-gateThe first argument (-name) is optional.  You can give the button a
66080Sstevel@tonic-gatename if you have several submission buttons in your form and you want
6609667Sps156622to distinguish between them.
66100Sstevel@tonic-gate
66110Sstevel@tonic-gate=item 2.
66120Sstevel@tonic-gate
66130Sstevel@tonic-gateThe second argument (-value) is also optional.  This gives the button
6614667Sps156622a value that will be passed to your script in the query string. The
6615667Sps156622name will also be used as the user-visible label.
6616667Sps156622
6617667Sps156622=item 3.
6618667Sps156622
6619667Sps156622You can use -label as an alias for -value.  I always get confused
6620667Sps156622about which of -name and -value changes the user-visible label on the
6621667Sps156622button.
66220Sstevel@tonic-gate
66230Sstevel@tonic-gate=back
66240Sstevel@tonic-gate
66250Sstevel@tonic-gateYou can figure out which button was pressed by using different
66260Sstevel@tonic-gatevalues for each one:
66270Sstevel@tonic-gate
6628667Sps156622     $which_one = param('button_name');
66290Sstevel@tonic-gate
66300Sstevel@tonic-gate=head2 CREATING A RESET BUTTON
66310Sstevel@tonic-gate
6632667Sps156622   print reset
66330Sstevel@tonic-gate
66340Sstevel@tonic-gatereset() creates the "reset" button.  Note that it restores the
66350Sstevel@tonic-gateform to its value from the last time the script was called,
66360Sstevel@tonic-gateNOT necessarily to the defaults.
66370Sstevel@tonic-gate
66380Sstevel@tonic-gateNote that this conflicts with the Perl reset() built-in.  Use
66390Sstevel@tonic-gateCORE::reset() to get the original reset function.
66400Sstevel@tonic-gate
66410Sstevel@tonic-gate=head2 CREATING A DEFAULT BUTTON
66420Sstevel@tonic-gate
6643667Sps156622   print defaults('button_label')
66440Sstevel@tonic-gate
66450Sstevel@tonic-gatedefaults() creates a button that, when invoked, will cause the
66460Sstevel@tonic-gateform to be completely reset to its defaults, wiping out all the
66470Sstevel@tonic-gatechanges the user ever made.
66480Sstevel@tonic-gate
66490Sstevel@tonic-gate=head2 CREATING A HIDDEN FIELD
66500Sstevel@tonic-gate
6651667Sps156622	print hidden(-name=>'hidden_name',
66520Sstevel@tonic-gate			     -default=>['value1','value2'...]);
66530Sstevel@tonic-gate
66540Sstevel@tonic-gate		-or-
66550Sstevel@tonic-gate
6656667Sps156622	print hidden('hidden_name','value1','value2'...);
66570Sstevel@tonic-gate
66580Sstevel@tonic-gatehidden() produces a text field that can't be seen by the user.  It
66590Sstevel@tonic-gateis useful for passing state variable information from one invocation
66600Sstevel@tonic-gateof the script to the next.
66610Sstevel@tonic-gate
66620Sstevel@tonic-gate=over 4
66630Sstevel@tonic-gate
66640Sstevel@tonic-gate=item B<Parameters:>
66650Sstevel@tonic-gate
66660Sstevel@tonic-gate=item 1.
66670Sstevel@tonic-gate
66680Sstevel@tonic-gateThe first argument is required and specifies the name of this
66690Sstevel@tonic-gatefield (-name).
66700Sstevel@tonic-gate
66710Sstevel@tonic-gate=item 2.
66720Sstevel@tonic-gate
66730Sstevel@tonic-gateThe second argument is also required and specifies its value
66740Sstevel@tonic-gate(-default).  In the named parameter style of calling, you can provide
66750Sstevel@tonic-gatea single value here or a reference to a whole list
66760Sstevel@tonic-gate
66770Sstevel@tonic-gate=back
66780Sstevel@tonic-gate
66790Sstevel@tonic-gateFetch the value of a hidden field this way:
66800Sstevel@tonic-gate
6681667Sps156622     $hidden_value = param('hidden_name');
66820Sstevel@tonic-gate
66830Sstevel@tonic-gateNote, that just like all the other form elements, the value of a
66840Sstevel@tonic-gatehidden field is "sticky".  If you want to replace a hidden field with
66850Sstevel@tonic-gatesome other values after the script has been called once you'll have to
66860Sstevel@tonic-gatedo it manually:
66870Sstevel@tonic-gate
6688667Sps156622     param('hidden_name','new','values','here');
66890Sstevel@tonic-gate
66900Sstevel@tonic-gate=head2 CREATING A CLICKABLE IMAGE BUTTON
66910Sstevel@tonic-gate
6692667Sps156622     print image_button(-name=>'button_name',
66930Sstevel@tonic-gate				-src=>'/source/URL',
66940Sstevel@tonic-gate				-align=>'MIDDLE');
66950Sstevel@tonic-gate
66960Sstevel@tonic-gate	-or-
66970Sstevel@tonic-gate
6698667Sps156622     print image_button('button_name','/source/URL','MIDDLE');
66990Sstevel@tonic-gate
67000Sstevel@tonic-gateimage_button() produces a clickable image.  When it's clicked on the
67010Sstevel@tonic-gateposition of the click is returned to your script as "button_name.x"
67020Sstevel@tonic-gateand "button_name.y", where "button_name" is the name you've assigned
67030Sstevel@tonic-gateto it.
67040Sstevel@tonic-gate
67050Sstevel@tonic-gate=over 4
67060Sstevel@tonic-gate
67070Sstevel@tonic-gate=item B<Parameters:>
67080Sstevel@tonic-gate
67090Sstevel@tonic-gate=item 1.
67100Sstevel@tonic-gate
67110Sstevel@tonic-gateThe first argument (-name) is required and specifies the name of this
67120Sstevel@tonic-gatefield.
67130Sstevel@tonic-gate
67140Sstevel@tonic-gate=item 2.
67150Sstevel@tonic-gate
67160Sstevel@tonic-gateThe second argument (-src) is also required and specifies the URL
67170Sstevel@tonic-gate
67180Sstevel@tonic-gate=item 3.
67190Sstevel@tonic-gateThe third option (-align, optional) is an alignment type, and may be
67200Sstevel@tonic-gateTOP, BOTTOM or MIDDLE
67210Sstevel@tonic-gate
67220Sstevel@tonic-gate=back
67230Sstevel@tonic-gate
67240Sstevel@tonic-gateFetch the value of the button this way:
6725667Sps156622     $x = param('button_name.x');
6726667Sps156622     $y = param('button_name.y');
67270Sstevel@tonic-gate
67280Sstevel@tonic-gate=head2 CREATING A JAVASCRIPT ACTION BUTTON
67290Sstevel@tonic-gate
6730667Sps156622     print button(-name=>'button_name',
67310Sstevel@tonic-gate			  -value=>'user visible label',
67320Sstevel@tonic-gate			  -onClick=>"do_something()");
67330Sstevel@tonic-gate
67340Sstevel@tonic-gate	-or-
67350Sstevel@tonic-gate
6736667Sps156622     print button('button_name',"do_something()");
67370Sstevel@tonic-gate
67380Sstevel@tonic-gatebutton() produces a button that is compatible with Netscape 2.0's
67390Sstevel@tonic-gateJavaScript.  When it's pressed the fragment of JavaScript code
67400Sstevel@tonic-gatepointed to by the B<-onClick> parameter will be executed.  On
67410Sstevel@tonic-gatenon-Netscape browsers this form element will probably not even
67420Sstevel@tonic-gatedisplay.
67430Sstevel@tonic-gate
67440Sstevel@tonic-gate=head1 HTTP COOKIES
67450Sstevel@tonic-gate
67460Sstevel@tonic-gateNetscape browsers versions 1.1 and higher, and all versions of
67470Sstevel@tonic-gateInternet Explorer, support a so-called "cookie" designed to help
67480Sstevel@tonic-gatemaintain state within a browser session.  CGI.pm has several methods
67490Sstevel@tonic-gatethat support cookies.
67500Sstevel@tonic-gate
67510Sstevel@tonic-gateA cookie is a name=value pair much like the named parameters in a CGI
67520Sstevel@tonic-gatequery string.  CGI scripts create one or more cookies and send
67530Sstevel@tonic-gatethem to the browser in the HTTP header.  The browser maintains a list
67540Sstevel@tonic-gateof cookies that belong to a particular Web server, and returns them
67550Sstevel@tonic-gateto the CGI script during subsequent interactions.
67560Sstevel@tonic-gate
67570Sstevel@tonic-gateIn addition to the required name=value pair, each cookie has several
67580Sstevel@tonic-gateoptional attributes:
67590Sstevel@tonic-gate
67600Sstevel@tonic-gate=over 4
67610Sstevel@tonic-gate
67620Sstevel@tonic-gate=item 1. an expiration time
67630Sstevel@tonic-gate
67640Sstevel@tonic-gateThis is a time/date string (in a special GMT format) that indicates
67650Sstevel@tonic-gatewhen a cookie expires.  The cookie will be saved and returned to your
67660Sstevel@tonic-gatescript until this expiration date is reached if the user exits
67670Sstevel@tonic-gatethe browser and restarts it.  If an expiration date isn't specified, the cookie
67680Sstevel@tonic-gatewill remain active until the user quits the browser.
67690Sstevel@tonic-gate
67700Sstevel@tonic-gate=item 2. a domain
67710Sstevel@tonic-gate
67720Sstevel@tonic-gateThis is a partial or complete domain name for which the cookie is
67730Sstevel@tonic-gatevalid.  The browser will return the cookie to any host that matches
67740Sstevel@tonic-gatethe partial domain name.  For example, if you specify a domain name
67750Sstevel@tonic-gateof ".capricorn.com", then the browser will return the cookie to
67760Sstevel@tonic-gateWeb servers running on any of the machines "www.capricorn.com",
67770Sstevel@tonic-gate"www2.capricorn.com", "feckless.capricorn.com", etc.  Domain names
67780Sstevel@tonic-gatemust contain at least two periods to prevent attempts to match
67790Sstevel@tonic-gateon top level domains like ".edu".  If no domain is specified, then
67800Sstevel@tonic-gatethe browser will only return the cookie to servers on the host the
67810Sstevel@tonic-gatecookie originated from.
67820Sstevel@tonic-gate
67830Sstevel@tonic-gate=item 3. a path
67840Sstevel@tonic-gate
67850Sstevel@tonic-gateIf you provide a cookie path attribute, the browser will check it
67860Sstevel@tonic-gateagainst your script's URL before returning the cookie.  For example,
67870Sstevel@tonic-gateif you specify the path "/cgi-bin", then the cookie will be returned
67880Sstevel@tonic-gateto each of the scripts "/cgi-bin/tally.pl", "/cgi-bin/order.pl",
67890Sstevel@tonic-gateand "/cgi-bin/customer_service/complain.pl", but not to the script
67900Sstevel@tonic-gate"/cgi-private/site_admin.pl".  By default, path is set to "/", which
67910Sstevel@tonic-gatecauses the cookie to be sent to any CGI script on your site.
67920Sstevel@tonic-gate
67930Sstevel@tonic-gate=item 4. a "secure" flag
67940Sstevel@tonic-gate
67950Sstevel@tonic-gateIf the "secure" attribute is set, the cookie will only be sent to your
67960Sstevel@tonic-gatescript if the CGI request is occurring on a secure channel, such as SSL.
67970Sstevel@tonic-gate
67980Sstevel@tonic-gate=back
67990Sstevel@tonic-gate
68000Sstevel@tonic-gateThe interface to HTTP cookies is the B<cookie()> method:
68010Sstevel@tonic-gate
6802667Sps156622    $cookie = cookie(-name=>'sessionID',
68030Sstevel@tonic-gate			     -value=>'xyzzy',
68040Sstevel@tonic-gate			     -expires=>'+1h',
68050Sstevel@tonic-gate			     -path=>'/cgi-bin/database',
68060Sstevel@tonic-gate			     -domain=>'.capricorn.org',
68070Sstevel@tonic-gate			     -secure=>1);
6808667Sps156622    print header(-cookie=>$cookie);
68090Sstevel@tonic-gate
68100Sstevel@tonic-gateB<cookie()> creates a new cookie.  Its parameters include:
68110Sstevel@tonic-gate
68120Sstevel@tonic-gate=over 4
68130Sstevel@tonic-gate
68140Sstevel@tonic-gate=item B<-name>
68150Sstevel@tonic-gate
68160Sstevel@tonic-gateThe name of the cookie (required).  This can be any string at all.
68170Sstevel@tonic-gateAlthough browsers limit their cookie names to non-whitespace
68180Sstevel@tonic-gatealphanumeric characters, CGI.pm removes this restriction by escaping
68190Sstevel@tonic-gateand unescaping cookies behind the scenes.
68200Sstevel@tonic-gate
68210Sstevel@tonic-gate=item B<-value>
68220Sstevel@tonic-gate
68230Sstevel@tonic-gateThe value of the cookie.  This can be any scalar value,
68240Sstevel@tonic-gatearray reference, or even associative array reference.  For example,
68250Sstevel@tonic-gateyou can store an entire associative array into a cookie this way:
68260Sstevel@tonic-gate
6827667Sps156622	$cookie=cookie(-name=>'family information',
68280Sstevel@tonic-gate			       -value=>\%childrens_ages);
68290Sstevel@tonic-gate
68300Sstevel@tonic-gate=item B<-path>
68310Sstevel@tonic-gate
68320Sstevel@tonic-gateThe optional partial path for which this cookie will be valid, as described
68330Sstevel@tonic-gateabove.
68340Sstevel@tonic-gate
68350Sstevel@tonic-gate=item B<-domain>
68360Sstevel@tonic-gate
68370Sstevel@tonic-gateThe optional partial domain for which this cookie will be valid, as described
68380Sstevel@tonic-gateabove.
68390Sstevel@tonic-gate
68400Sstevel@tonic-gate=item B<-expires>
68410Sstevel@tonic-gate
68420Sstevel@tonic-gateThe optional expiration date for this cookie.  The format is as described
68430Sstevel@tonic-gatein the section on the B<header()> method:
68440Sstevel@tonic-gate
68450Sstevel@tonic-gate	"+1h"  one hour from now
68460Sstevel@tonic-gate
68470Sstevel@tonic-gate=item B<-secure>
68480Sstevel@tonic-gate
68490Sstevel@tonic-gateIf set to true, this cookie will only be used within a secure
68500Sstevel@tonic-gateSSL session.
68510Sstevel@tonic-gate
68520Sstevel@tonic-gate=back
68530Sstevel@tonic-gate
68540Sstevel@tonic-gateThe cookie created by cookie() must be incorporated into the HTTP
68550Sstevel@tonic-gateheader within the string returned by the header() method:
68560Sstevel@tonic-gate
6857*6287Sps156622        use CGI ':standard';
6858667Sps156622	print header(-cookie=>$my_cookie);
68590Sstevel@tonic-gate
68600Sstevel@tonic-gateTo create multiple cookies, give header() an array reference:
68610Sstevel@tonic-gate
6862667Sps156622	$cookie1 = cookie(-name=>'riddle_name',
68630Sstevel@tonic-gate				  -value=>"The Sphynx's Question");
6864667Sps156622	$cookie2 = cookie(-name=>'answers',
68650Sstevel@tonic-gate				  -value=>\%answers);
6866667Sps156622	print header(-cookie=>[$cookie1,$cookie2]);
68670Sstevel@tonic-gate
68680Sstevel@tonic-gateTo retrieve a cookie, request it by name by calling cookie() method
6869*6287Sps156622without the B<-value> parameter. This example uses the object-oriented
6870*6287Sps156622form:
68710Sstevel@tonic-gate
68720Sstevel@tonic-gate	use CGI;
68730Sstevel@tonic-gate	$query = new CGI;
6874*6287Sps156622	$riddle = $query->cookie('riddle_name');
6875*6287Sps156622        %answers = $query->cookie('answers');
68760Sstevel@tonic-gate
68770Sstevel@tonic-gateCookies created with a single scalar value, such as the "riddle_name"
68780Sstevel@tonic-gatecookie, will be returned in that form.  Cookies with array and hash
68790Sstevel@tonic-gatevalues can also be retrieved.
68800Sstevel@tonic-gate
68810Sstevel@tonic-gateThe cookie and CGI namespaces are separate.  If you have a parameter
68820Sstevel@tonic-gatenamed 'answers' and a cookie named 'answers', the values retrieved by
68830Sstevel@tonic-gateparam() and cookie() are independent of each other.  However, it's
68840Sstevel@tonic-gatesimple to turn a CGI parameter into a cookie, and vice-versa:
68850Sstevel@tonic-gate
68860Sstevel@tonic-gate   # turn a CGI parameter into a cookie
6887667Sps156622   $c=cookie(-name=>'answers',-value=>[param('answers')]);
68880Sstevel@tonic-gate   # vice-versa
6889667Sps156622   param(-name=>'answers',-value=>[cookie('answers')]);
68900Sstevel@tonic-gate
6891*6287Sps156622If you call cookie() without any parameters, it will return a list of
6892*6287Sps156622the names of all cookies passed to your script:
6893*6287Sps156622
6894*6287Sps156622  @cookies = cookie();
6895*6287Sps156622
68960Sstevel@tonic-gateSee the B<cookie.cgi> example script for some ideas on how to use
68970Sstevel@tonic-gatecookies effectively.
68980Sstevel@tonic-gate
68990Sstevel@tonic-gate=head1 WORKING WITH FRAMES
69000Sstevel@tonic-gate
69010Sstevel@tonic-gateIt's possible for CGI.pm scripts to write into several browser panels
69020Sstevel@tonic-gateand windows using the HTML 4 frame mechanism.  There are three
69030Sstevel@tonic-gatetechniques for defining new frames programmatically:
69040Sstevel@tonic-gate
69050Sstevel@tonic-gate=over 4
69060Sstevel@tonic-gate
69070Sstevel@tonic-gate=item 1. Create a <Frameset> document
69080Sstevel@tonic-gate
69090Sstevel@tonic-gateAfter writing out the HTTP header, instead of creating a standard
69100Sstevel@tonic-gateHTML document using the start_html() call, create a <frameset>
69110Sstevel@tonic-gatedocument that defines the frames on the page.  Specify your script(s)
69120Sstevel@tonic-gate(with appropriate parameters) as the SRC for each of the frames.
69130Sstevel@tonic-gate
69140Sstevel@tonic-gateThere is no specific support for creating <frameset> sections
69150Sstevel@tonic-gatein CGI.pm, but the HTML is very simple to write.  See the frame
69160Sstevel@tonic-gatedocumentation in Netscape's home pages for details
69170Sstevel@tonic-gate
6918*6287Sps156622  http://wp.netscape.com/assist/net_sites/frames.html
69190Sstevel@tonic-gate
69200Sstevel@tonic-gate=item 2. Specify the destination for the document in the HTTP header
69210Sstevel@tonic-gate
69220Sstevel@tonic-gateYou may provide a B<-target> parameter to the header() method:
69230Sstevel@tonic-gate
6924667Sps156622    print header(-target=>'ResultsWindow');
69250Sstevel@tonic-gate
69260Sstevel@tonic-gateThis will tell the browser to load the output of your script into the
69270Sstevel@tonic-gateframe named "ResultsWindow".  If a frame of that name doesn't already
69280Sstevel@tonic-gateexist, the browser will pop up a new window and load your script's
69290Sstevel@tonic-gatedocument into that.  There are a number of magic names that you can
69300Sstevel@tonic-gateuse for targets.  See the frame documents on Netscape's home pages for
69310Sstevel@tonic-gatedetails.
69320Sstevel@tonic-gate
69330Sstevel@tonic-gate=item 3. Specify the destination for the document in the <form> tag
69340Sstevel@tonic-gate
69350Sstevel@tonic-gateYou can specify the frame to load in the FORM tag itself.  With
69360Sstevel@tonic-gateCGI.pm it looks like this:
69370Sstevel@tonic-gate
6938667Sps156622    print start_form(-target=>'ResultsWindow');
69390Sstevel@tonic-gate
69400Sstevel@tonic-gateWhen your script is reinvoked by the form, its output will be loaded
69410Sstevel@tonic-gateinto the frame named "ResultsWindow".  If one doesn't already exist
69420Sstevel@tonic-gatea new window will be created.
69430Sstevel@tonic-gate
69440Sstevel@tonic-gate=back
69450Sstevel@tonic-gate
69460Sstevel@tonic-gateThe script "frameset.cgi" in the examples directory shows one way to
69470Sstevel@tonic-gatecreate pages in which the fill-out form and the response live in
69480Sstevel@tonic-gateside-by-side frames.
69490Sstevel@tonic-gate
6950667Sps156622=head1 SUPPORT FOR JAVASCRIPT
6951667Sps156622
6952667Sps156622Netscape versions 2.0 and higher incorporate an interpreted language
6953667Sps156622called JavaScript. Internet Explorer, 3.0 and higher, supports a
6954667Sps156622closely-related dialect called JScript. JavaScript isn't the same as
6955667Sps156622Java, and certainly isn't at all the same as Perl, which is a great
6956*6287Sps156622pity. JavaScript allows you to programmatically change the contents of
6957667Sps156622fill-out forms, create new windows, and pop up dialog box from within
6958667Sps156622Netscape itself. From the point of view of CGI scripting, JavaScript
6959667Sps156622is quite useful for validating fill-out forms prior to submitting
6960667Sps156622them.
6961667Sps156622
6962667Sps156622You'll need to know JavaScript in order to use it. There are many good
6963667Sps156622sources in bookstores and on the web.
6964667Sps156622
6965667Sps156622The usual way to use JavaScript is to define a set of functions in a
6966667Sps156622<SCRIPT> block inside the HTML header and then to register event
6967667Sps156622handlers in the various elements of the page. Events include such
6968667Sps156622things as the mouse passing over a form element, a button being
6969667Sps156622clicked, the contents of a text field changing, or a form being
6970667Sps156622submitted. When an event occurs that involves an element that has
6971667Sps156622registered an event handler, its associated JavaScript code gets
6972667Sps156622called.
6973667Sps156622
6974667Sps156622The elements that can register event handlers include the <BODY> of an
6975667Sps156622HTML document, hypertext links, all the various elements of a fill-out
6976667Sps156622form, and the form itself. There are a large number of events, and
6977667Sps156622each applies only to the elements for which it is relevant. Here is a
6978667Sps156622partial list:
6979667Sps156622
6980667Sps156622=over 4
6981667Sps156622
6982667Sps156622=item B<onLoad>
6983667Sps156622
6984667Sps156622The browser is loading the current document. Valid in:
6985667Sps156622
6986667Sps156622     + The HTML <BODY> section only.
6987667Sps156622
6988667Sps156622=item B<onUnload>
6989667Sps156622
6990667Sps156622The browser is closing the current page or frame. Valid for:
6991667Sps156622
6992667Sps156622     + The HTML <BODY> section only.
6993667Sps156622
6994667Sps156622=item B<onSubmit>
6995667Sps156622
6996667Sps156622The user has pressed the submit button of a form. This event happens
6997667Sps156622just before the form is submitted, and your function can return a
6998667Sps156622value of false in order to abort the submission.  Valid for:
6999667Sps156622
7000667Sps156622     + Forms only.
7001667Sps156622
7002667Sps156622=item B<onClick>
7003667Sps156622
7004667Sps156622The mouse has clicked on an item in a fill-out form. Valid for:
7005667Sps156622
7006667Sps156622     + Buttons (including submit, reset, and image buttons)
7007667Sps156622     + Checkboxes
7008667Sps156622     + Radio buttons
7009667Sps156622
7010667Sps156622=item B<onChange>
7011667Sps156622
7012667Sps156622The user has changed the contents of a field. Valid for:
7013667Sps156622
7014667Sps156622     + Text fields
7015667Sps156622     + Text areas
7016667Sps156622     + Password fields
7017667Sps156622     + File fields
7018667Sps156622     + Popup Menus
7019667Sps156622     + Scrolling lists
7020667Sps156622
7021667Sps156622=item B<onFocus>
7022667Sps156622
7023667Sps156622The user has selected a field to work with. Valid for:
7024667Sps156622
7025667Sps156622     + Text fields
7026667Sps156622     + Text areas
7027667Sps156622     + Password fields
7028667Sps156622     + File fields
7029667Sps156622     + Popup Menus
7030667Sps156622     + Scrolling lists
7031667Sps156622
7032667Sps156622=item B<onBlur>
7033667Sps156622
7034667Sps156622The user has deselected a field (gone to work somewhere else).  Valid
7035667Sps156622for:
7036667Sps156622
7037667Sps156622     + Text fields
7038667Sps156622     + Text areas
7039667Sps156622     + Password fields
7040667Sps156622     + File fields
7041667Sps156622     + Popup Menus
7042667Sps156622     + Scrolling lists
7043667Sps156622
7044667Sps156622=item B<onSelect>
7045667Sps156622
7046667Sps156622The user has changed the part of a text field that is selected.  Valid
7047667Sps156622for:
7048667Sps156622
7049667Sps156622     + Text fields
7050667Sps156622     + Text areas
7051667Sps156622     + Password fields
7052667Sps156622     + File fields
7053667Sps156622
7054667Sps156622=item B<onMouseOver>
7055667Sps156622
7056667Sps156622The mouse has moved over an element.
7057667Sps156622
7058667Sps156622     + Text fields
7059667Sps156622     + Text areas
7060667Sps156622     + Password fields
7061667Sps156622     + File fields
7062667Sps156622     + Popup Menus
7063667Sps156622     + Scrolling lists
7064667Sps156622
7065667Sps156622=item B<onMouseOut>
7066667Sps156622
7067667Sps156622The mouse has moved off an element.
7068667Sps156622
7069667Sps156622     + Text fields
7070667Sps156622     + Text areas
7071667Sps156622     + Password fields
7072667Sps156622     + File fields
7073667Sps156622     + Popup Menus
7074667Sps156622     + Scrolling lists
7075667Sps156622
7076667Sps156622=back
7077667Sps156622
7078667Sps156622In order to register a JavaScript event handler with an HTML element,
7079667Sps156622just use the event name as a parameter when you call the corresponding
7080667Sps156622CGI method. For example, to have your validateAge() JavaScript code
7081667Sps156622executed every time the textfield named "age" changes, generate the
7082667Sps156622field like this:
7083667Sps156622
7084667Sps156622 print textfield(-name=>'age',-onChange=>"validateAge(this)");
7085667Sps156622
7086667Sps156622This example assumes that you've already declared the validateAge()
7087667Sps156622function by incorporating it into a <SCRIPT> block. The CGI.pm
7088667Sps156622start_html() method provides a convenient way to create this section.
7089667Sps156622
7090667Sps156622Similarly, you can create a form that checks itself over for
7091667Sps156622consistency and alerts the user if some essential value is missing by
7092667Sps156622creating it this way:
7093667Sps156622  print startform(-onSubmit=>"validateMe(this)");
7094667Sps156622
7095667Sps156622See the javascript.cgi script for a demonstration of how this all
7096667Sps156622works.
7097667Sps156622
7098667Sps156622
70990Sstevel@tonic-gate=head1 LIMITED SUPPORT FOR CASCADING STYLE SHEETS
71000Sstevel@tonic-gate
71010Sstevel@tonic-gateCGI.pm has limited support for HTML3's cascading style sheets (css).
71020Sstevel@tonic-gateTo incorporate a stylesheet into your document, pass the
71030Sstevel@tonic-gatestart_html() method a B<-style> parameter.  The value of this
71040Sstevel@tonic-gateparameter may be a scalar, in which case it is treated as the source
71050Sstevel@tonic-gateURL for the stylesheet, or it may be a hash reference.  In the latter
71060Sstevel@tonic-gatecase you should provide the hash with one or more of B<-src> or
71070Sstevel@tonic-gateB<-code>.  B<-src> points to a URL where an externally-defined
71080Sstevel@tonic-gatestylesheet can be found.  B<-code> points to a scalar value to be
71090Sstevel@tonic-gateincorporated into a <style> section.  Style definitions in B<-code>
71100Sstevel@tonic-gateoverride similarly-named ones in B<-src>, hence the name "cascading."
71110Sstevel@tonic-gate
71120Sstevel@tonic-gateYou may also specify the type of the stylesheet by adding the optional
71130Sstevel@tonic-gateB<-type> parameter to the hash pointed to by B<-style>.  If not
71140Sstevel@tonic-gatespecified, the style defaults to 'text/css'.
71150Sstevel@tonic-gate
71160Sstevel@tonic-gateTo refer to a style within the body of your document, add the
71170Sstevel@tonic-gateB<-class> parameter to any HTML element:
71180Sstevel@tonic-gate
71190Sstevel@tonic-gate    print h1({-class=>'Fancy'},'Welcome to the Party');
71200Sstevel@tonic-gate
71210Sstevel@tonic-gateOr define styles on the fly with the B<-style> parameter:
71220Sstevel@tonic-gate
71230Sstevel@tonic-gate    print h1({-style=>'Color: red;'},'Welcome to Hell');
71240Sstevel@tonic-gate
71250Sstevel@tonic-gateYou may also use the new B<span()> element to apply a style to a
71260Sstevel@tonic-gatesection of text:
71270Sstevel@tonic-gate
71280Sstevel@tonic-gate    print span({-style=>'Color: red;'},
71290Sstevel@tonic-gate	       h1('Welcome to Hell'),
71300Sstevel@tonic-gate	       "Where did that handbasket get to?"
71310Sstevel@tonic-gate	       );
71320Sstevel@tonic-gate
71330Sstevel@tonic-gateNote that you must import the ":html3" definitions to have the
71340Sstevel@tonic-gateB<span()> method available.  Here's a quick and dirty example of using
71350Sstevel@tonic-gateCSS's.  See the CSS specification at
71360Sstevel@tonic-gatehttp://www.w3.org/pub/WWW/TR/Wd-css-1.html for more information.
71370Sstevel@tonic-gate
71380Sstevel@tonic-gate    use CGI qw/:standard :html3/;
71390Sstevel@tonic-gate
71400Sstevel@tonic-gate    #here's a stylesheet incorporated directly into the page
71410Sstevel@tonic-gate    $newStyle=<<END;
71420Sstevel@tonic-gate    <!--
71430Sstevel@tonic-gate    P.Tip {
71440Sstevel@tonic-gate	margin-right: 50pt;
71450Sstevel@tonic-gate	margin-left: 50pt;
71460Sstevel@tonic-gate        color: red;
71470Sstevel@tonic-gate    }
71480Sstevel@tonic-gate    P.Alert {
71490Sstevel@tonic-gate	font-size: 30pt;
71500Sstevel@tonic-gate        font-family: sans-serif;
71510Sstevel@tonic-gate      color: red;
71520Sstevel@tonic-gate    }
71530Sstevel@tonic-gate    -->
71540Sstevel@tonic-gate    END
71550Sstevel@tonic-gate    print header();
71560Sstevel@tonic-gate    print start_html( -title=>'CGI with Style',
71570Sstevel@tonic-gate		      -style=>{-src=>'http://www.capricorn.com/style/st1.css',
71580Sstevel@tonic-gate		               -code=>$newStyle}
71590Sstevel@tonic-gate	             );
71600Sstevel@tonic-gate    print h1('CGI with Style'),
71610Sstevel@tonic-gate          p({-class=>'Tip'},
71620Sstevel@tonic-gate	    "Better read the cascading style sheet spec before playing with this!"),
71630Sstevel@tonic-gate          span({-style=>'color: magenta'},
71640Sstevel@tonic-gate	       "Look Mom, no hands!",
71650Sstevel@tonic-gate	       p(),
71660Sstevel@tonic-gate	       "Whooo wee!"
71670Sstevel@tonic-gate	       );
71680Sstevel@tonic-gate    print end_html;
71690Sstevel@tonic-gate
7170667Sps156622Pass an array reference to B<-code> or B<-src> in order to incorporate
7171667Sps156622multiple stylesheets into your document.
71720Sstevel@tonic-gate
71730Sstevel@tonic-gateShould you wish to incorporate a verbatim stylesheet that includes
71740Sstevel@tonic-gatearbitrary formatting in the header, you may pass a -verbatim tag to
71750Sstevel@tonic-gatethe -style hash, as follows:
71760Sstevel@tonic-gate
7177*6287Sps156622print start_html (-style  =>  {-verbatim => '@import url("/server-common/css/'.$cssFile.'");',
7178*6287Sps156622                  -src    =>  '/server-common/css/core.css'});
71790Sstevel@tonic-gate
71800Sstevel@tonic-gate
71810Sstevel@tonic-gateThis will generate an HTML header that contains this:
71820Sstevel@tonic-gate
71830Sstevel@tonic-gate <link rel="stylesheet" type="text/css"  href="/server-common/css/core.css">
71840Sstevel@tonic-gate   <style type="text/css">
71850Sstevel@tonic-gate   @import url("/server-common/css/main.css");
71860Sstevel@tonic-gate   </style>
71870Sstevel@tonic-gate
71880Sstevel@tonic-gateAny additional arguments passed in the -style value will be
71890Sstevel@tonic-gateincorporated into the <link> tag.  For example:
71900Sstevel@tonic-gate
71910Sstevel@tonic-gate start_html(-style=>{-src=>['/styles/print.css','/styles/layout.css'],
71920Sstevel@tonic-gate			  -media => 'all'});
71930Sstevel@tonic-gate
71940Sstevel@tonic-gateThis will give:
71950Sstevel@tonic-gate
71960Sstevel@tonic-gate <link rel="stylesheet" type="text/css" href="/styles/print.css" media="all"/>
71970Sstevel@tonic-gate <link rel="stylesheet" type="text/css" href="/styles/layout.css" media="all"/>
71980Sstevel@tonic-gate
71990Sstevel@tonic-gate<p>
72000Sstevel@tonic-gate
72010Sstevel@tonic-gateTo make more complicated <link> tags, use the Link() function
72020Sstevel@tonic-gateand pass it to start_html() in the -head argument, as in:
72030Sstevel@tonic-gate
72040Sstevel@tonic-gate  @h = (Link({-rel=>'stylesheet',-type=>'text/css',-src=>'/ss/ss.css',-media=>'all'}),
72050Sstevel@tonic-gate        Link({-rel=>'stylesheet',-type=>'text/css',-src=>'/ss/fred.css',-media=>'paper'}));
72060Sstevel@tonic-gate  print start_html({-head=>\@h})
72070Sstevel@tonic-gate
7208*6287Sps156622To create primary and  "alternate" stylesheet, use the B<-alternate> option:
7209*6287Sps156622
7210*6287Sps156622 start_html(-style=>{-src=>[
7211*6287Sps156622                           {-src=>'/styles/print.css'},
7212*6287Sps156622			   {-src=>'/styles/alt.css',-alternate=>1}
7213*6287Sps156622                           ]
7214*6287Sps156622		    });
7215*6287Sps156622
72160Sstevel@tonic-gate=head1 DEBUGGING
72170Sstevel@tonic-gate
72180Sstevel@tonic-gateIf you are running the script from the command line or in the perl
72190Sstevel@tonic-gatedebugger, you can pass the script a list of keywords or
72200Sstevel@tonic-gateparameter=value pairs on the command line or from standard input (you
72210Sstevel@tonic-gatedon't have to worry about tricking your script into reading from
72220Sstevel@tonic-gateenvironment variables).  You can pass keywords like this:
72230Sstevel@tonic-gate
72240Sstevel@tonic-gate    your_script.pl keyword1 keyword2 keyword3
72250Sstevel@tonic-gate
72260Sstevel@tonic-gateor this:
72270Sstevel@tonic-gate
72280Sstevel@tonic-gate   your_script.pl keyword1+keyword2+keyword3
72290Sstevel@tonic-gate
72300Sstevel@tonic-gateor this:
72310Sstevel@tonic-gate
72320Sstevel@tonic-gate    your_script.pl name1=value1 name2=value2
72330Sstevel@tonic-gate
72340Sstevel@tonic-gateor this:
72350Sstevel@tonic-gate
72360Sstevel@tonic-gate    your_script.pl name1=value1&name2=value2
72370Sstevel@tonic-gate
72380Sstevel@tonic-gateTo turn off this feature, use the -no_debug pragma.
72390Sstevel@tonic-gate
72400Sstevel@tonic-gateTo test the POST method, you may enable full debugging with the -debug
72410Sstevel@tonic-gatepragma.  This will allow you to feed newline-delimited name=value
72420Sstevel@tonic-gatepairs to the script on standard input.
72430Sstevel@tonic-gate
72440Sstevel@tonic-gateWhen debugging, you can use quotes and backslashes to escape
72450Sstevel@tonic-gatecharacters in the familiar shell manner, letting you place
72460Sstevel@tonic-gatespaces and other funny characters in your parameter=value
72470Sstevel@tonic-gatepairs:
72480Sstevel@tonic-gate
72490Sstevel@tonic-gate   your_script.pl "name1='I am a long value'" "name2=two\ words"
72500Sstevel@tonic-gate
72510Sstevel@tonic-gateFinally, you can set the path info for the script by prefixing the first
72520Sstevel@tonic-gatename/value parameter with the path followed by a question mark (?):
72530Sstevel@tonic-gate
72540Sstevel@tonic-gate    your_script.pl /your/path/here?name1=value1&name2=value2
72550Sstevel@tonic-gate
72560Sstevel@tonic-gate=head2 DUMPING OUT ALL THE NAME/VALUE PAIRS
72570Sstevel@tonic-gate
72580Sstevel@tonic-gateThe Dump() method produces a string consisting of all the query's
72590Sstevel@tonic-gatename/value pairs formatted nicely as a nested list.  This is useful
72600Sstevel@tonic-gatefor debugging purposes:
72610Sstevel@tonic-gate
7262667Sps156622    print Dump
72630Sstevel@tonic-gate
72640Sstevel@tonic-gate
72650Sstevel@tonic-gateProduces something that looks like:
72660Sstevel@tonic-gate
72670Sstevel@tonic-gate    <ul>
72680Sstevel@tonic-gate    <li>name1
72690Sstevel@tonic-gate	<ul>
72700Sstevel@tonic-gate	<li>value1
72710Sstevel@tonic-gate	<li>value2
72720Sstevel@tonic-gate	</ul>
72730Sstevel@tonic-gate    <li>name2
72740Sstevel@tonic-gate	<ul>
72750Sstevel@tonic-gate	<li>value1
72760Sstevel@tonic-gate	</ul>
72770Sstevel@tonic-gate    </ul>
72780Sstevel@tonic-gate
72790Sstevel@tonic-gateAs a shortcut, you can interpolate the entire CGI object into a string
72800Sstevel@tonic-gateand it will be replaced with the a nice HTML dump shown above:
72810Sstevel@tonic-gate
72820Sstevel@tonic-gate    $query=new CGI;
72830Sstevel@tonic-gate    print "<h2>Current Values</h2> $query\n";
72840Sstevel@tonic-gate
72850Sstevel@tonic-gate=head1 FETCHING ENVIRONMENT VARIABLES
72860Sstevel@tonic-gate
72870Sstevel@tonic-gateSome of the more useful environment variables can be fetched
72880Sstevel@tonic-gatethrough this interface.  The methods are as follows:
72890Sstevel@tonic-gate
72900Sstevel@tonic-gate=over 4
72910Sstevel@tonic-gate
72920Sstevel@tonic-gate=item B<Accept()>
72930Sstevel@tonic-gate
72940Sstevel@tonic-gateReturn a list of MIME types that the remote browser accepts. If you
72950Sstevel@tonic-gategive this method a single argument corresponding to a MIME type, as in
7296667Sps156622Accept('text/html'), it will return a floating point value
72970Sstevel@tonic-gatecorresponding to the browser's preference for this type from 0.0
72980Sstevel@tonic-gate(don't want) to 1.0.  Glob types (e.g. text/*) in the browser's accept
72990Sstevel@tonic-gatelist are handled correctly.
73000Sstevel@tonic-gate
73010Sstevel@tonic-gateNote that the capitalization changed between version 2.43 and 2.44 in
73020Sstevel@tonic-gateorder to avoid conflict with Perl's accept() function.
73030Sstevel@tonic-gate
73040Sstevel@tonic-gate=item B<raw_cookie()>
73050Sstevel@tonic-gate
73060Sstevel@tonic-gateReturns the HTTP_COOKIE variable, an HTTP extension implemented by
73070Sstevel@tonic-gateNetscape browsers version 1.1 and higher, and all versions of Internet
73080Sstevel@tonic-gateExplorer.  Cookies have a special format, and this method call just
73090Sstevel@tonic-gatereturns the raw form (?cookie dough).  See cookie() for ways of
73100Sstevel@tonic-gatesetting and retrieving cooked cookies.
73110Sstevel@tonic-gate
73120Sstevel@tonic-gateCalled with no parameters, raw_cookie() returns the packed cookie
73130Sstevel@tonic-gatestructure.  You can separate it into individual cookies by splitting
73140Sstevel@tonic-gateon the character sequence "; ".  Called with the name of a cookie,
73150Sstevel@tonic-gateretrieves the B<unescaped> form of the cookie.  You can use the
73160Sstevel@tonic-gateregular cookie() method to get the names, or use the raw_fetch()
73170Sstevel@tonic-gatemethod from the CGI::Cookie module.
73180Sstevel@tonic-gate
73190Sstevel@tonic-gate=item B<user_agent()>
73200Sstevel@tonic-gate
73210Sstevel@tonic-gateReturns the HTTP_USER_AGENT variable.  If you give
73220Sstevel@tonic-gatethis method a single argument, it will attempt to
73230Sstevel@tonic-gatepattern match on it, allowing you to do something
7324667Sps156622like user_agent(netscape);
73250Sstevel@tonic-gate
73260Sstevel@tonic-gate=item B<path_info()>
73270Sstevel@tonic-gate
73280Sstevel@tonic-gateReturns additional path information from the script URL.
73290Sstevel@tonic-gateE.G. fetching /cgi-bin/your_script/additional/stuff will result in
7330667Sps156622path_info() returning "/additional/stuff".
73310Sstevel@tonic-gate
73320Sstevel@tonic-gateNOTE: The Microsoft Internet Information Server
73330Sstevel@tonic-gateis broken with respect to additional path information.  If
73340Sstevel@tonic-gateyou use the Perl DLL library, the IIS server will attempt to
73350Sstevel@tonic-gateexecute the additional path information as a Perl script.
73360Sstevel@tonic-gateIf you use the ordinary file associations mapping, the
73370Sstevel@tonic-gatepath information will be present in the environment,
73380Sstevel@tonic-gatebut incorrect.  The best thing to do is to avoid using additional
73390Sstevel@tonic-gatepath information in CGI scripts destined for use with IIS.
73400Sstevel@tonic-gate
73410Sstevel@tonic-gate=item B<path_translated()>
73420Sstevel@tonic-gate
73430Sstevel@tonic-gateAs per path_info() but returns the additional
73440Sstevel@tonic-gatepath information translated into a physical path, e.g.
73450Sstevel@tonic-gate"/usr/local/etc/httpd/htdocs/additional/stuff".
73460Sstevel@tonic-gate
73470Sstevel@tonic-gateThe Microsoft IIS is broken with respect to the translated
73480Sstevel@tonic-gatepath as well.
73490Sstevel@tonic-gate
73500Sstevel@tonic-gate=item B<remote_host()>
73510Sstevel@tonic-gate
73520Sstevel@tonic-gateReturns either the remote host name or IP address.
73530Sstevel@tonic-gateif the former is unavailable.
73540Sstevel@tonic-gate
73550Sstevel@tonic-gate=item B<script_name()>
73560Sstevel@tonic-gateReturn the script name as a partial URL, for self-refering
73570Sstevel@tonic-gatescripts.
73580Sstevel@tonic-gate
73590Sstevel@tonic-gate=item B<referer()>
73600Sstevel@tonic-gate
73610Sstevel@tonic-gateReturn the URL of the page the browser was viewing
73620Sstevel@tonic-gateprior to fetching your script.  Not available for all
73630Sstevel@tonic-gatebrowsers.
73640Sstevel@tonic-gate
73650Sstevel@tonic-gate=item B<auth_type ()>
73660Sstevel@tonic-gate
73670Sstevel@tonic-gateReturn the authorization/verification method in use for this
73680Sstevel@tonic-gatescript, if any.
73690Sstevel@tonic-gate
73700Sstevel@tonic-gate=item B<server_name ()>
73710Sstevel@tonic-gate
73720Sstevel@tonic-gateReturns the name of the server, usually the machine's host
73730Sstevel@tonic-gatename.
73740Sstevel@tonic-gate
73750Sstevel@tonic-gate=item B<virtual_host ()>
73760Sstevel@tonic-gate
73770Sstevel@tonic-gateWhen using virtual hosts, returns the name of the host that
73780Sstevel@tonic-gatethe browser attempted to contact
73790Sstevel@tonic-gate
73800Sstevel@tonic-gate=item B<server_port ()>
73810Sstevel@tonic-gate
73820Sstevel@tonic-gateReturn the port that the server is listening on.
73830Sstevel@tonic-gate
73840Sstevel@tonic-gate=item B<virtual_port ()>
73850Sstevel@tonic-gate
73860Sstevel@tonic-gateLike server_port() except that it takes virtual hosts into account.
73870Sstevel@tonic-gateUse this when running with virtual hosts.
73880Sstevel@tonic-gate
73890Sstevel@tonic-gate=item B<server_software ()>
73900Sstevel@tonic-gate
73910Sstevel@tonic-gateReturns the server software and version number.
73920Sstevel@tonic-gate
73930Sstevel@tonic-gate=item B<remote_user ()>
73940Sstevel@tonic-gate
73950Sstevel@tonic-gateReturn the authorization/verification name used for user
73960Sstevel@tonic-gateverification, if this script is protected.
73970Sstevel@tonic-gate
73980Sstevel@tonic-gate=item B<user_name ()>
73990Sstevel@tonic-gate
74000Sstevel@tonic-gateAttempt to obtain the remote user's name, using a variety of different
74010Sstevel@tonic-gatetechniques.  This only works with older browsers such as Mosaic.
74020Sstevel@tonic-gateNewer browsers do not report the user name for privacy reasons!
74030Sstevel@tonic-gate
74040Sstevel@tonic-gate=item B<request_method()>
74050Sstevel@tonic-gate
74060Sstevel@tonic-gateReturns the method used to access your script, usually
74070Sstevel@tonic-gateone of 'POST', 'GET' or 'HEAD'.
74080Sstevel@tonic-gate
74090Sstevel@tonic-gate=item B<content_type()>
74100Sstevel@tonic-gate
74110Sstevel@tonic-gateReturns the content_type of data submitted in a POST, generally
74120Sstevel@tonic-gatemultipart/form-data or application/x-www-form-urlencoded
74130Sstevel@tonic-gate
74140Sstevel@tonic-gate=item B<http()>
74150Sstevel@tonic-gate
74160Sstevel@tonic-gateCalled with no arguments returns the list of HTTP environment
74170Sstevel@tonic-gatevariables, including such things as HTTP_USER_AGENT,
74180Sstevel@tonic-gateHTTP_ACCEPT_LANGUAGE, and HTTP_ACCEPT_CHARSET, corresponding to the
74190Sstevel@tonic-gatelike-named HTTP header fields in the request.  Called with the name of
74200Sstevel@tonic-gatean HTTP header field, returns its value.  Capitalization and the use
74210Sstevel@tonic-gateof hyphens versus underscores are not significant.
74220Sstevel@tonic-gate
74230Sstevel@tonic-gateFor example, all three of these examples are equivalent:
74240Sstevel@tonic-gate
7425667Sps156622   $requested_language = http('Accept-language');
7426667Sps156622   $requested_language = http('Accept_language');
7427667Sps156622   $requested_language = http('HTTP_ACCEPT_LANGUAGE');
74280Sstevel@tonic-gate
74290Sstevel@tonic-gate=item B<https()>
74300Sstevel@tonic-gate
74310Sstevel@tonic-gateThe same as I<http()>, but operates on the HTTPS environment variables
74320Sstevel@tonic-gatepresent when the SSL protocol is in effect.  Can be used to determine
74330Sstevel@tonic-gatewhether SSL is turned on.
74340Sstevel@tonic-gate
74350Sstevel@tonic-gate=back
74360Sstevel@tonic-gate
74370Sstevel@tonic-gate=head1 USING NPH SCRIPTS
74380Sstevel@tonic-gate
74390Sstevel@tonic-gateNPH, or "no-parsed-header", scripts bypass the server completely by
74400Sstevel@tonic-gatesending the complete HTTP header directly to the browser.  This has
74410Sstevel@tonic-gateslight performance benefits, but is of most use for taking advantage
74420Sstevel@tonic-gateof HTTP extensions that are not directly supported by your server,
74430Sstevel@tonic-gatesuch as server push and PICS headers.
74440Sstevel@tonic-gate
74450Sstevel@tonic-gateServers use a variety of conventions for designating CGI scripts as
74460Sstevel@tonic-gateNPH.  Many Unix servers look at the beginning of the script's name for
74470Sstevel@tonic-gatethe prefix "nph-".  The Macintosh WebSTAR server and Microsoft's
74480Sstevel@tonic-gateInternet Information Server, in contrast, try to decide whether a
74490Sstevel@tonic-gateprogram is an NPH script by examining the first line of script output.
74500Sstevel@tonic-gate
74510Sstevel@tonic-gate
74520Sstevel@tonic-gateCGI.pm supports NPH scripts with a special NPH mode.  When in this
74530Sstevel@tonic-gatemode, CGI.pm will output the necessary extra header information when
74540Sstevel@tonic-gatethe header() and redirect() methods are
74550Sstevel@tonic-gatecalled.
74560Sstevel@tonic-gate
74570Sstevel@tonic-gateThe Microsoft Internet Information Server requires NPH mode.  As of
74580Sstevel@tonic-gateversion 2.30, CGI.pm will automatically detect when the script is
74590Sstevel@tonic-gaterunning under IIS and put itself into this mode.  You do not need to
74600Sstevel@tonic-gatedo this manually, although it won't hurt anything if you do.  However,
74610Sstevel@tonic-gatenote that if you have applied Service Pack 6, much of the
74620Sstevel@tonic-gatefunctionality of NPH scripts, including the ability to redirect while
74630Sstevel@tonic-gatesetting a cookie, b<do not work at all> on IIS without a special patch
74640Sstevel@tonic-gatefrom Microsoft.  See
74650Sstevel@tonic-gatehttp://support.microsoft.com/support/kb/articles/Q280/3/41.ASP:
74660Sstevel@tonic-gateNon-Parsed Headers Stripped From CGI Applications That Have nph-
74670Sstevel@tonic-gatePrefix in Name.
74680Sstevel@tonic-gate
74690Sstevel@tonic-gate=over 4
74700Sstevel@tonic-gate
74710Sstevel@tonic-gate=item In the B<use> statement
74720Sstevel@tonic-gate
74730Sstevel@tonic-gateSimply add the "-nph" pragmato the list of symbols to be imported into
74740Sstevel@tonic-gateyour script:
74750Sstevel@tonic-gate
74760Sstevel@tonic-gate      use CGI qw(:standard -nph)
74770Sstevel@tonic-gate
74780Sstevel@tonic-gate=item By calling the B<nph()> method:
74790Sstevel@tonic-gate
74800Sstevel@tonic-gateCall B<nph()> with a non-zero parameter at any point after using CGI.pm in your program.
74810Sstevel@tonic-gate
74820Sstevel@tonic-gate      CGI->nph(1)
74830Sstevel@tonic-gate
74840Sstevel@tonic-gate=item By using B<-nph> parameters
74850Sstevel@tonic-gate
74860Sstevel@tonic-gatein the B<header()> and B<redirect()>  statements:
74870Sstevel@tonic-gate
7488667Sps156622      print header(-nph=>1);
74890Sstevel@tonic-gate
74900Sstevel@tonic-gate=back
74910Sstevel@tonic-gate
74920Sstevel@tonic-gate=head1 Server Push
74930Sstevel@tonic-gate
74940Sstevel@tonic-gateCGI.pm provides four simple functions for producing multipart
74950Sstevel@tonic-gatedocuments of the type needed to implement server push.  These
74960Sstevel@tonic-gatefunctions were graciously provided by Ed Jordan <ed@fidalgo.net>.  To
74970Sstevel@tonic-gateimport these into your namespace, you must import the ":push" set.
74980Sstevel@tonic-gateYou are also advised to put the script into NPH mode and to set $| to
74990Sstevel@tonic-gate1 to avoid buffering problems.
75000Sstevel@tonic-gate
75010Sstevel@tonic-gateHere is a simple script that demonstrates server push:
75020Sstevel@tonic-gate
75030Sstevel@tonic-gate  #!/usr/local/bin/perl
75040Sstevel@tonic-gate  use CGI qw/:push -nph/;
75050Sstevel@tonic-gate  $| = 1;
75060Sstevel@tonic-gate  print multipart_init(-boundary=>'----here we go!');
75070Sstevel@tonic-gate  foreach (0 .. 4) {
75080Sstevel@tonic-gate      print multipart_start(-type=>'text/plain'),
75090Sstevel@tonic-gate            "The current time is ",scalar(localtime),"\n";
75100Sstevel@tonic-gate      if ($_ < 4) {
75110Sstevel@tonic-gate              print multipart_end;
75120Sstevel@tonic-gate      } else {
75130Sstevel@tonic-gate              print multipart_final;
75140Sstevel@tonic-gate      }
75150Sstevel@tonic-gate      sleep 1;
75160Sstevel@tonic-gate  }
75170Sstevel@tonic-gate
75180Sstevel@tonic-gateThis script initializes server push by calling B<multipart_init()>.
75190Sstevel@tonic-gateIt then enters a loop in which it begins a new multipart section by
75200Sstevel@tonic-gatecalling B<multipart_start()>, prints the current local time,
75210Sstevel@tonic-gateand ends a multipart section with B<multipart_end()>.  It then sleeps
75220Sstevel@tonic-gatea second, and begins again. On the final iteration, it ends the
75230Sstevel@tonic-gatemultipart section with B<multipart_final()> rather than with
75240Sstevel@tonic-gateB<multipart_end()>.
75250Sstevel@tonic-gate
75260Sstevel@tonic-gate=over 4
75270Sstevel@tonic-gate
75280Sstevel@tonic-gate=item multipart_init()
75290Sstevel@tonic-gate
75300Sstevel@tonic-gate  multipart_init(-boundary=>$boundary);
75310Sstevel@tonic-gate
75320Sstevel@tonic-gateInitialize the multipart system.  The -boundary argument specifies
75330Sstevel@tonic-gatewhat MIME boundary string to use to separate parts of the document.
75340Sstevel@tonic-gateIf not provided, CGI.pm chooses a reasonable boundary for you.
75350Sstevel@tonic-gate
75360Sstevel@tonic-gate=item multipart_start()
75370Sstevel@tonic-gate
75380Sstevel@tonic-gate  multipart_start(-type=>$type)
75390Sstevel@tonic-gate
75400Sstevel@tonic-gateStart a new part of the multipart document using the specified MIME
75410Sstevel@tonic-gatetype.  If not specified, text/html is assumed.
75420Sstevel@tonic-gate
75430Sstevel@tonic-gate=item multipart_end()
75440Sstevel@tonic-gate
75450Sstevel@tonic-gate  multipart_end()
75460Sstevel@tonic-gate
75470Sstevel@tonic-gateEnd a part.  You must remember to call multipart_end() once for each
75480Sstevel@tonic-gatemultipart_start(), except at the end of the last part of the multipart
75490Sstevel@tonic-gatedocument when multipart_final() should be called instead of multipart_end().
75500Sstevel@tonic-gate
75510Sstevel@tonic-gate=item multipart_final()
75520Sstevel@tonic-gate
75530Sstevel@tonic-gate  multipart_final()
75540Sstevel@tonic-gate
75550Sstevel@tonic-gateEnd all parts.  You should call multipart_final() rather than
75560Sstevel@tonic-gatemultipart_end() at the end of the last part of the multipart document.
75570Sstevel@tonic-gate
75580Sstevel@tonic-gate=back
75590Sstevel@tonic-gate
75600Sstevel@tonic-gateUsers interested in server push applications should also have a look
75610Sstevel@tonic-gateat the CGI::Push module.
75620Sstevel@tonic-gate
75630Sstevel@tonic-gateOnly Netscape Navigator supports server push.  Internet Explorer
75640Sstevel@tonic-gatebrowsers do not.
75650Sstevel@tonic-gate
75660Sstevel@tonic-gate=head1 Avoiding Denial of Service Attacks
75670Sstevel@tonic-gate
75680Sstevel@tonic-gateA potential problem with CGI.pm is that, by default, it attempts to
75690Sstevel@tonic-gateprocess form POSTings no matter how large they are.  A wily hacker
75700Sstevel@tonic-gatecould attack your site by sending a CGI script a huge POST of many
75710Sstevel@tonic-gatemegabytes.  CGI.pm will attempt to read the entire POST into a
75720Sstevel@tonic-gatevariable, growing hugely in size until it runs out of memory.  While
75730Sstevel@tonic-gatethe script attempts to allocate the memory the system may slow down
75740Sstevel@tonic-gatedramatically.  This is a form of denial of service attack.
75750Sstevel@tonic-gate
75760Sstevel@tonic-gateAnother possible attack is for the remote user to force CGI.pm to
75770Sstevel@tonic-gateaccept a huge file upload.  CGI.pm will accept the upload and store it
75780Sstevel@tonic-gatein a temporary directory even if your script doesn't expect to receive
75790Sstevel@tonic-gatean uploaded file.  CGI.pm will delete the file automatically when it
75800Sstevel@tonic-gateterminates, but in the meantime the remote user may have filled up the
75810Sstevel@tonic-gateserver's disk space, causing problems for other programs.
75820Sstevel@tonic-gate
75830Sstevel@tonic-gateThe best way to avoid denial of service attacks is to limit the amount
75840Sstevel@tonic-gateof memory, CPU time and disk space that CGI scripts can use.  Some Web
75850Sstevel@tonic-gateservers come with built-in facilities to accomplish this. In other
75860Sstevel@tonic-gatecases, you can use the shell I<limit> or I<ulimit>
75870Sstevel@tonic-gatecommands to put ceilings on CGI resource usage.
75880Sstevel@tonic-gate
75890Sstevel@tonic-gate
75900Sstevel@tonic-gateCGI.pm also has some simple built-in protections against denial of
75910Sstevel@tonic-gateservice attacks, but you must activate them before you can use them.
75920Sstevel@tonic-gateThese take the form of two global variables in the CGI name space:
75930Sstevel@tonic-gate
75940Sstevel@tonic-gate=over 4
75950Sstevel@tonic-gate
75960Sstevel@tonic-gate=item B<$CGI::POST_MAX>
75970Sstevel@tonic-gate
75980Sstevel@tonic-gateIf set to a non-negative integer, this variable puts a ceiling
75990Sstevel@tonic-gateon the size of POSTings, in bytes.  If CGI.pm detects a POST
76000Sstevel@tonic-gatethat is greater than the ceiling, it will immediately exit with an error
76010Sstevel@tonic-gatemessage.  This value will affect both ordinary POSTs and
76020Sstevel@tonic-gatemultipart POSTs, meaning that it limits the maximum size of file
76030Sstevel@tonic-gateuploads as well.  You should set this to a reasonably high
76040Sstevel@tonic-gatevalue, such as 1 megabyte.
76050Sstevel@tonic-gate
76060Sstevel@tonic-gate=item B<$CGI::DISABLE_UPLOADS>
76070Sstevel@tonic-gate
76080Sstevel@tonic-gateIf set to a non-zero value, this will disable file uploads
76090Sstevel@tonic-gatecompletely.  Other fill-out form values will work as usual.
76100Sstevel@tonic-gate
76110Sstevel@tonic-gate=back
76120Sstevel@tonic-gate
76130Sstevel@tonic-gateYou can use these variables in either of two ways.
76140Sstevel@tonic-gate
76150Sstevel@tonic-gate=over 4
76160Sstevel@tonic-gate
76170Sstevel@tonic-gate=item B<1. On a script-by-script basis>
76180Sstevel@tonic-gate
76190Sstevel@tonic-gateSet the variable at the top of the script, right after the "use" statement:
76200Sstevel@tonic-gate
76210Sstevel@tonic-gate    use CGI qw/:standard/;
76220Sstevel@tonic-gate    use CGI::Carp 'fatalsToBrowser';
76230Sstevel@tonic-gate    $CGI::POST_MAX=1024 * 100;  # max 100K posts
76240Sstevel@tonic-gate    $CGI::DISABLE_UPLOADS = 1;  # no uploads
76250Sstevel@tonic-gate
76260Sstevel@tonic-gate=item B<2. Globally for all scripts>
76270Sstevel@tonic-gate
76280Sstevel@tonic-gateOpen up CGI.pm, find the definitions for $POST_MAX and
76290Sstevel@tonic-gate$DISABLE_UPLOADS, and set them to the desired values.  You'll
76300Sstevel@tonic-gatefind them towards the top of the file in a subroutine named
76310Sstevel@tonic-gateinitialize_globals().
76320Sstevel@tonic-gate
76330Sstevel@tonic-gate=back
76340Sstevel@tonic-gate
76350Sstevel@tonic-gateAn attempt to send a POST larger than $POST_MAX bytes will cause
76360Sstevel@tonic-gateI<param()> to return an empty CGI parameter list.  You can test for
76370Sstevel@tonic-gatethis event by checking I<cgi_error()>, either after you create the CGI
76380Sstevel@tonic-gateobject or, if you are using the function-oriented interface, call
76390Sstevel@tonic-gate<param()> for the first time.  If the POST was intercepted, then
76400Sstevel@tonic-gatecgi_error() will return the message "413 POST too large".
76410Sstevel@tonic-gate
76420Sstevel@tonic-gateThis error message is actually defined by the HTTP protocol, and is
76430Sstevel@tonic-gatedesigned to be returned to the browser as the CGI script's status
76440Sstevel@tonic-gate code.  For example:
76450Sstevel@tonic-gate
76460Sstevel@tonic-gate   $uploaded_file = param('upload');
76470Sstevel@tonic-gate   if (!$uploaded_file && cgi_error()) {
76480Sstevel@tonic-gate      print header(-status=>cgi_error());
76490Sstevel@tonic-gate      exit 0;
76500Sstevel@tonic-gate   }
76510Sstevel@tonic-gate
76520Sstevel@tonic-gateHowever it isn't clear that any browser currently knows what to do
76530Sstevel@tonic-gatewith this status code.  It might be better just to create an
76540Sstevel@tonic-gateHTML page that warns the user of the problem.
76550Sstevel@tonic-gate
76560Sstevel@tonic-gate=head1 COMPATIBILITY WITH CGI-LIB.PL
76570Sstevel@tonic-gate
76580Sstevel@tonic-gateTo make it easier to port existing programs that use cgi-lib.pl the
76590Sstevel@tonic-gatecompatibility routine "ReadParse" is provided.  Porting is simple:
76600Sstevel@tonic-gate
76610Sstevel@tonic-gateOLD VERSION
76620Sstevel@tonic-gate    require "cgi-lib.pl";
76630Sstevel@tonic-gate    &ReadParse;
76640Sstevel@tonic-gate    print "The value of the antique is $in{antique}.\n";
76650Sstevel@tonic-gate
76660Sstevel@tonic-gateNEW VERSION
76670Sstevel@tonic-gate    use CGI;
7668*6287Sps156622    CGI::ReadParse();
76690Sstevel@tonic-gate    print "The value of the antique is $in{antique}.\n";
76700Sstevel@tonic-gate
76710Sstevel@tonic-gateCGI.pm's ReadParse() routine creates a tied variable named %in,
76720Sstevel@tonic-gatewhich can be accessed to obtain the query variables.  Like
76730Sstevel@tonic-gateReadParse, you can also provide your own variable.  Infrequently
76740Sstevel@tonic-gateused features of ReadParse, such as the creation of @in and $in
76750Sstevel@tonic-gatevariables, are not supported.
76760Sstevel@tonic-gate
76770Sstevel@tonic-gateOnce you use ReadParse, you can retrieve the query object itself
76780Sstevel@tonic-gatethis way:
76790Sstevel@tonic-gate
76800Sstevel@tonic-gate    $q = $in{CGI};
7681667Sps156622    print textfield(-name=>'wow',
76820Sstevel@tonic-gate			-value=>'does this really work?');
76830Sstevel@tonic-gate
76840Sstevel@tonic-gateThis allows you to start using the more interesting features
76850Sstevel@tonic-gateof CGI.pm without rewriting your old scripts from scratch.
76860Sstevel@tonic-gate
76870Sstevel@tonic-gate=head1 AUTHOR INFORMATION
76880Sstevel@tonic-gate
76890Sstevel@tonic-gateCopyright 1995-1998, Lincoln D. Stein.  All rights reserved.
76900Sstevel@tonic-gate
76910Sstevel@tonic-gateThis library is free software; you can redistribute it and/or modify
76920Sstevel@tonic-gateit under the same terms as Perl itself.
76930Sstevel@tonic-gate
76940Sstevel@tonic-gateAddress bug reports and comments to: lstein@cshl.org.  When sending
76950Sstevel@tonic-gatebug reports, please provide the version of CGI.pm, the version of
76960Sstevel@tonic-gatePerl, the name and version of your Web server, and the name and
76970Sstevel@tonic-gateversion of the operating system you are using.  If the problem is even
76980Sstevel@tonic-gateremotely browser dependent, please provide information about the
76990Sstevel@tonic-gateaffected browers as well.
77000Sstevel@tonic-gate
77010Sstevel@tonic-gate=head1 CREDITS
77020Sstevel@tonic-gate
77030Sstevel@tonic-gateThanks very much to:
77040Sstevel@tonic-gate
77050Sstevel@tonic-gate=over 4
77060Sstevel@tonic-gate
77070Sstevel@tonic-gate=item Matt Heffron (heffron@falstaff.css.beckman.com)
77080Sstevel@tonic-gate
77090Sstevel@tonic-gate=item James Taylor (james.taylor@srs.gov)
77100Sstevel@tonic-gate
77110Sstevel@tonic-gate=item Scott Anguish <sanguish@digifix.com>
77120Sstevel@tonic-gate
77130Sstevel@tonic-gate=item Mike Jewell (mlj3u@virginia.edu)
77140Sstevel@tonic-gate
77150Sstevel@tonic-gate=item Timothy Shimmin (tes@kbs.citri.edu.au)
77160Sstevel@tonic-gate
77170Sstevel@tonic-gate=item Joergen Haegg (jh@axis.se)
77180Sstevel@tonic-gate
77190Sstevel@tonic-gate=item Laurent Delfosse (delfosse@delfosse.com)
77200Sstevel@tonic-gate
77210Sstevel@tonic-gate=item Richard Resnick (applepi1@aol.com)
77220Sstevel@tonic-gate
77230Sstevel@tonic-gate=item Craig Bishop (csb@barwonwater.vic.gov.au)
77240Sstevel@tonic-gate
77250Sstevel@tonic-gate=item Tony Curtis (tc@vcpc.univie.ac.at)
77260Sstevel@tonic-gate
77270Sstevel@tonic-gate=item Tim Bunce (Tim.Bunce@ig.co.uk)
77280Sstevel@tonic-gate
77290Sstevel@tonic-gate=item Tom Christiansen (tchrist@convex.com)
77300Sstevel@tonic-gate
77310Sstevel@tonic-gate=item Andreas Koenig (k@franz.ww.TU-Berlin.DE)
77320Sstevel@tonic-gate
77330Sstevel@tonic-gate=item Tim MacKenzie (Tim.MacKenzie@fulcrum.com.au)
77340Sstevel@tonic-gate
77350Sstevel@tonic-gate=item Kevin B. Hendricks (kbhend@dogwood.tyler.wm.edu)
77360Sstevel@tonic-gate
77370Sstevel@tonic-gate=item Stephen Dahmen (joyfire@inxpress.net)
77380Sstevel@tonic-gate
77390Sstevel@tonic-gate=item Ed Jordan (ed@fidalgo.net)
77400Sstevel@tonic-gate
77410Sstevel@tonic-gate=item David Alan Pisoni (david@cnation.com)
77420Sstevel@tonic-gate
77430Sstevel@tonic-gate=item Doug MacEachern (dougm@opengroup.org)
77440Sstevel@tonic-gate
77450Sstevel@tonic-gate=item Robin Houston (robin@oneworld.org)
77460Sstevel@tonic-gate
77470Sstevel@tonic-gate=item ...and many many more...
77480Sstevel@tonic-gate
77490Sstevel@tonic-gatefor suggestions and bug fixes.
77500Sstevel@tonic-gate
77510Sstevel@tonic-gate=back
77520Sstevel@tonic-gate
77530Sstevel@tonic-gate=head1 A COMPLETE EXAMPLE OF A SIMPLE FORM-BASED SCRIPT
77540Sstevel@tonic-gate
77550Sstevel@tonic-gate
77560Sstevel@tonic-gate	#!/usr/local/bin/perl
77570Sstevel@tonic-gate
7758667Sps156622	use CGI ':standard';
7759667Sps156622
7760667Sps156622	print header;
7761667Sps156622	print start_html("Example CGI.pm Form");
77620Sstevel@tonic-gate	print "<h1> Example CGI.pm Form</h1>\n";
7763667Sps156622        print_prompt();
7764667Sps156622	do_work();
7765667Sps156622	print_tail();
7766667Sps156622	print end_html;
77670Sstevel@tonic-gate
77680Sstevel@tonic-gate	sub print_prompt {
7769667Sps156622	   print start_form;
77700Sstevel@tonic-gate	   print "<em>What's your name?</em><br>";
7771667Sps156622	   print textfield('name');
7772667Sps156622	   print checkbox('Not my real name');
77730Sstevel@tonic-gate
77740Sstevel@tonic-gate	   print "<p><em>Where can you find English Sparrows?</em><br>";
7775667Sps156622	   print checkbox_group(
77760Sstevel@tonic-gate				 -name=>'Sparrow locations',
77770Sstevel@tonic-gate				 -values=>[England,France,Spain,Asia,Hoboken],
77780Sstevel@tonic-gate				 -linebreak=>'yes',
77790Sstevel@tonic-gate				 -defaults=>[England,Asia]);
77800Sstevel@tonic-gate
77810Sstevel@tonic-gate	   print "<p><em>How far can they fly?</em><br>",
7782667Sps156622		radio_group(
77830Sstevel@tonic-gate			-name=>'how far',
77840Sstevel@tonic-gate			-values=>['10 ft','1 mile','10 miles','real far'],
77850Sstevel@tonic-gate			-default=>'1 mile');
77860Sstevel@tonic-gate
77870Sstevel@tonic-gate	   print "<p><em>What's your favorite color?</em>  ";
7788667Sps156622	   print popup_menu(-name=>'Color',
77890Sstevel@tonic-gate				    -values=>['black','brown','red','yellow'],
77900Sstevel@tonic-gate				    -default=>'red');
77910Sstevel@tonic-gate
7792667Sps156622	   print hidden('Reference','Monty Python and the Holy Grail');
77930Sstevel@tonic-gate
77940Sstevel@tonic-gate	   print "<p><em>What have you got there?</em><br>";
7795667Sps156622	   print scrolling_list(
77960Sstevel@tonic-gate			 -name=>'possessions',
77970Sstevel@tonic-gate			 -values=>['A Coconut','A Grail','An Icon',
77980Sstevel@tonic-gate				   'A Sword','A Ticket'],
77990Sstevel@tonic-gate			 -size=>5,
78000Sstevel@tonic-gate			 -multiple=>'true');
78010Sstevel@tonic-gate
78020Sstevel@tonic-gate	   print "<p><em>Any parting comments?</em><br>";
7803667Sps156622	   print textarea(-name=>'Comments',
78040Sstevel@tonic-gate				  -rows=>10,
78050Sstevel@tonic-gate				  -columns=>50);
78060Sstevel@tonic-gate
7807667Sps156622	   print "<p>",reset;
7808667Sps156622	   print submit('Action','Shout');
7809667Sps156622	   print submit('Action','Scream');
7810667Sps156622	   print endform;
78110Sstevel@tonic-gate	   print "<hr>\n";
78120Sstevel@tonic-gate	}
78130Sstevel@tonic-gate
78140Sstevel@tonic-gate	sub do_work {
78150Sstevel@tonic-gate	   my(@values,$key);
78160Sstevel@tonic-gate
78170Sstevel@tonic-gate	   print "<h2>Here are the current settings in this form</h2>";
78180Sstevel@tonic-gate
7819667Sps156622	   foreach $key (param) {
78200Sstevel@tonic-gate	      print "<strong>$key</strong> -> ";
7821667Sps156622	      @values = param($key);
78220Sstevel@tonic-gate	      print join(", ",@values),"<br>\n";
78230Sstevel@tonic-gate	  }
78240Sstevel@tonic-gate	}
78250Sstevel@tonic-gate
78260Sstevel@tonic-gate	sub print_tail {
78270Sstevel@tonic-gate	   print <<END;
78280Sstevel@tonic-gate	<hr>
78290Sstevel@tonic-gate	<address>Lincoln D. Stein</address><br>
78300Sstevel@tonic-gate	<a href="/">Home Page</a>
78310Sstevel@tonic-gate	END
78320Sstevel@tonic-gate	}
78330Sstevel@tonic-gate
78340Sstevel@tonic-gate=head1 BUGS
78350Sstevel@tonic-gate
78360Sstevel@tonic-gatePlease report them.
78370Sstevel@tonic-gate
78380Sstevel@tonic-gate=head1 SEE ALSO
78390Sstevel@tonic-gate
78400Sstevel@tonic-gateL<CGI::Carp>, L<CGI::Fast>, L<CGI::Pretty>
78410Sstevel@tonic-gate
78420Sstevel@tonic-gate=cut
78430Sstevel@tonic-gate
7844