1*0Sstevel@tonic-gatepackage CGI; 2*0Sstevel@tonic-gaterequire 5.004; 3*0Sstevel@tonic-gateuse Carp 'croak'; 4*0Sstevel@tonic-gate 5*0Sstevel@tonic-gate# See the bottom of this file for the POD documentation. Search for the 6*0Sstevel@tonic-gate# string '=head'. 7*0Sstevel@tonic-gate 8*0Sstevel@tonic-gate# You can run this file through either pod2man or pod2html to produce pretty 9*0Sstevel@tonic-gate# documentation in manual or html file format (these utilities are part of the 10*0Sstevel@tonic-gate# Perl 5 distribution). 11*0Sstevel@tonic-gate 12*0Sstevel@tonic-gate# Copyright 1995-1998 Lincoln D. Stein. All rights reserved. 13*0Sstevel@tonic-gate# It may be used and modified freely, but I do request that this copyright 14*0Sstevel@tonic-gate# notice remain attached to the file. You may modify this module as you 15*0Sstevel@tonic-gate# wish, but if you redistribute a modified version, please attach a note 16*0Sstevel@tonic-gate# listing the modifications you have made. 17*0Sstevel@tonic-gate 18*0Sstevel@tonic-gate# The most recent version and complete docs are available at: 19*0Sstevel@tonic-gate# http://stein.cshl.org/WWW/software/CGI/ 20*0Sstevel@tonic-gate 21*0Sstevel@tonic-gate$CGI::revision = '$Id: CGI.pm,v 1.151 2004/01/13 16:28:35 lstein Exp $'; 22*0Sstevel@tonic-gate$CGI::VERSION=3.04; 23*0Sstevel@tonic-gate 24*0Sstevel@tonic-gate# HARD-CODED LOCATION FOR FILE UPLOAD TEMPORARY FILES. 25*0Sstevel@tonic-gate# UNCOMMENT THIS ONLY IF YOU KNOW WHAT YOU'RE DOING. 26*0Sstevel@tonic-gate# $CGITempFile::TMPDIRECTORY = '/usr/tmp'; 27*0Sstevel@tonic-gateuse CGI::Util qw(rearrange make_attributes unescape escape expires ebcdic2ascii ascii2ebcdic); 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate#use constant XHTML_DTD => ['-//W3C//DTD XHTML Basic 1.0//EN', 30*0Sstevel@tonic-gate# 'http://www.w3.org/TR/xhtml-basic/xhtml-basic10.dtd']; 31*0Sstevel@tonic-gate 32*0Sstevel@tonic-gateuse constant XHTML_DTD => ['-//W3C//DTD XHTML 1.0 Transitional//EN', 33*0Sstevel@tonic-gate 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd']; 34*0Sstevel@tonic-gate 35*0Sstevel@tonic-gate{ 36*0Sstevel@tonic-gate local $^W = 0; 37*0Sstevel@tonic-gate $TAINTED = substr("$0$^X",0,0); 38*0Sstevel@tonic-gate} 39*0Sstevel@tonic-gate 40*0Sstevel@tonic-gatemy @SAVED_SYMBOLS; 41*0Sstevel@tonic-gate 42*0Sstevel@tonic-gate$MOD_PERL = 0; # no mod_perl by default 43*0Sstevel@tonic-gate 44*0Sstevel@tonic-gate# >>>>> Here are some globals that you might want to adjust <<<<<< 45*0Sstevel@tonic-gatesub initialize_globals { 46*0Sstevel@tonic-gate # Set this to 1 to enable copious autoloader debugging messages 47*0Sstevel@tonic-gate $AUTOLOAD_DEBUG = 0; 48*0Sstevel@tonic-gate 49*0Sstevel@tonic-gate # Set this to 1 to generate XTML-compatible output 50*0Sstevel@tonic-gate $XHTML = 1; 51*0Sstevel@tonic-gate 52*0Sstevel@tonic-gate # Change this to the preferred DTD to print in start_html() 53*0Sstevel@tonic-gate # or use default_dtd('text of DTD to use'); 54*0Sstevel@tonic-gate $DEFAULT_DTD = [ '-//W3C//DTD HTML 4.01 Transitional//EN', 55*0Sstevel@tonic-gate 'http://www.w3.org/TR/html4/loose.dtd' ] ; 56*0Sstevel@tonic-gate 57*0Sstevel@tonic-gate # Set this to 1 to enable NOSTICKY scripts 58*0Sstevel@tonic-gate # or: 59*0Sstevel@tonic-gate # 1) use CGI qw(-nosticky) 60*0Sstevel@tonic-gate # 2) $CGI::nosticky(1) 61*0Sstevel@tonic-gate $NOSTICKY = 0; 62*0Sstevel@tonic-gate 63*0Sstevel@tonic-gate # Set this to 1 to enable NPH scripts 64*0Sstevel@tonic-gate # or: 65*0Sstevel@tonic-gate # 1) use CGI qw(-nph) 66*0Sstevel@tonic-gate # 2) CGI::nph(1) 67*0Sstevel@tonic-gate # 3) print header(-nph=>1) 68*0Sstevel@tonic-gate $NPH = 0; 69*0Sstevel@tonic-gate 70*0Sstevel@tonic-gate # Set this to 1 to enable debugging from @ARGV 71*0Sstevel@tonic-gate # Set to 2 to enable debugging from STDIN 72*0Sstevel@tonic-gate $DEBUG = 1; 73*0Sstevel@tonic-gate 74*0Sstevel@tonic-gate # Set this to 1 to make the temporary files created 75*0Sstevel@tonic-gate # during file uploads safe from prying eyes 76*0Sstevel@tonic-gate # or do... 77*0Sstevel@tonic-gate # 1) use CGI qw(:private_tempfiles) 78*0Sstevel@tonic-gate # 2) CGI::private_tempfiles(1); 79*0Sstevel@tonic-gate $PRIVATE_TEMPFILES = 0; 80*0Sstevel@tonic-gate 81*0Sstevel@tonic-gate # Set this to 1 to cause files uploaded in multipart documents 82*0Sstevel@tonic-gate # to be closed, instead of caching the file handle 83*0Sstevel@tonic-gate # or: 84*0Sstevel@tonic-gate # 1) use CGI qw(:close_upload_files) 85*0Sstevel@tonic-gate # 2) $CGI::close_upload_files(1); 86*0Sstevel@tonic-gate # Uploads with many files run out of file handles. 87*0Sstevel@tonic-gate # Also, for performance, since the file is already on disk, 88*0Sstevel@tonic-gate # it can just be renamed, instead of read and written. 89*0Sstevel@tonic-gate $CLOSE_UPLOAD_FILES = 0; 90*0Sstevel@tonic-gate 91*0Sstevel@tonic-gate # Set this to a positive value to limit the size of a POSTing 92*0Sstevel@tonic-gate # to a certain number of bytes: 93*0Sstevel@tonic-gate $POST_MAX = -1; 94*0Sstevel@tonic-gate 95*0Sstevel@tonic-gate # Change this to 1 to disable uploads entirely: 96*0Sstevel@tonic-gate $DISABLE_UPLOADS = 0; 97*0Sstevel@tonic-gate 98*0Sstevel@tonic-gate # Automatically determined -- don't change 99*0Sstevel@tonic-gate $EBCDIC = 0; 100*0Sstevel@tonic-gate 101*0Sstevel@tonic-gate # Change this to 1 to suppress redundant HTTP headers 102*0Sstevel@tonic-gate $HEADERS_ONCE = 0; 103*0Sstevel@tonic-gate 104*0Sstevel@tonic-gate # separate the name=value pairs by semicolons rather than ampersands 105*0Sstevel@tonic-gate $USE_PARAM_SEMICOLONS = 1; 106*0Sstevel@tonic-gate 107*0Sstevel@tonic-gate # Do not include undefined params parsed from query string 108*0Sstevel@tonic-gate # use CGI qw(-no_undef_params); 109*0Sstevel@tonic-gate $NO_UNDEF_PARAMS = 0; 110*0Sstevel@tonic-gate 111*0Sstevel@tonic-gate # Other globals that you shouldn't worry about. 112*0Sstevel@tonic-gate undef $Q; 113*0Sstevel@tonic-gate $BEEN_THERE = 0; 114*0Sstevel@tonic-gate undef @QUERY_PARAM; 115*0Sstevel@tonic-gate undef %EXPORT; 116*0Sstevel@tonic-gate undef $QUERY_CHARSET; 117*0Sstevel@tonic-gate undef %QUERY_FIELDNAMES; 118*0Sstevel@tonic-gate 119*0Sstevel@tonic-gate # prevent complaints by mod_perl 120*0Sstevel@tonic-gate 1; 121*0Sstevel@tonic-gate} 122*0Sstevel@tonic-gate 123*0Sstevel@tonic-gate# ------------------ START OF THE LIBRARY ------------ 124*0Sstevel@tonic-gate 125*0Sstevel@tonic-gate# make mod_perlhappy 126*0Sstevel@tonic-gateinitialize_globals(); 127*0Sstevel@tonic-gate 128*0Sstevel@tonic-gate# FIGURE OUT THE OS WE'RE RUNNING UNDER 129*0Sstevel@tonic-gate# Some systems support the $^O variable. If not 130*0Sstevel@tonic-gate# available then require() the Config library 131*0Sstevel@tonic-gateunless ($OS) { 132*0Sstevel@tonic-gate unless ($OS = $^O) { 133*0Sstevel@tonic-gate require Config; 134*0Sstevel@tonic-gate $OS = $Config::Config{'osname'}; 135*0Sstevel@tonic-gate } 136*0Sstevel@tonic-gate} 137*0Sstevel@tonic-gateif ($OS =~ /^MSWin/i) { 138*0Sstevel@tonic-gate $OS = 'WINDOWS'; 139*0Sstevel@tonic-gate} elsif ($OS =~ /^VMS/i) { 140*0Sstevel@tonic-gate $OS = 'VMS'; 141*0Sstevel@tonic-gate} elsif ($OS =~ /^dos/i) { 142*0Sstevel@tonic-gate $OS = 'DOS'; 143*0Sstevel@tonic-gate} elsif ($OS =~ /^MacOS/i) { 144*0Sstevel@tonic-gate $OS = 'MACINTOSH'; 145*0Sstevel@tonic-gate} elsif ($OS =~ /^os2/i) { 146*0Sstevel@tonic-gate $OS = 'OS2'; 147*0Sstevel@tonic-gate} elsif ($OS =~ /^epoc/i) { 148*0Sstevel@tonic-gate $OS = 'EPOC'; 149*0Sstevel@tonic-gate} elsif ($OS =~ /^cygwin/i) { 150*0Sstevel@tonic-gate $OS = 'CYGWIN'; 151*0Sstevel@tonic-gate} else { 152*0Sstevel@tonic-gate $OS = 'UNIX'; 153*0Sstevel@tonic-gate} 154*0Sstevel@tonic-gate 155*0Sstevel@tonic-gate# Some OS logic. Binary mode enabled on DOS, NT and VMS 156*0Sstevel@tonic-gate$needs_binmode = $OS=~/^(WINDOWS|DOS|OS2|MSWin|CYGWIN)/; 157*0Sstevel@tonic-gate 158*0Sstevel@tonic-gate# This is the default class for the CGI object to use when all else fails. 159*0Sstevel@tonic-gate$DefaultClass = 'CGI' unless defined $CGI::DefaultClass; 160*0Sstevel@tonic-gate 161*0Sstevel@tonic-gate# This is where to look for autoloaded routines. 162*0Sstevel@tonic-gate$AutoloadClass = $DefaultClass unless defined $CGI::AutoloadClass; 163*0Sstevel@tonic-gate 164*0Sstevel@tonic-gate# The path separator is a slash, backslash or semicolon, depending 165*0Sstevel@tonic-gate# on the paltform. 166*0Sstevel@tonic-gate$SL = { 167*0Sstevel@tonic-gate UNIX => '/', OS2 => '\\', EPOC => '/', CYGWIN => '/', 168*0Sstevel@tonic-gate WINDOWS => '\\', DOS => '\\', MACINTOSH => ':', VMS => '/' 169*0Sstevel@tonic-gate }->{$OS}; 170*0Sstevel@tonic-gate 171*0Sstevel@tonic-gate# This no longer seems to be necessary 172*0Sstevel@tonic-gate# Turn on NPH scripts by default when running under IIS server! 173*0Sstevel@tonic-gate# $NPH++ if defined($ENV{'SERVER_SOFTWARE'}) && $ENV{'SERVER_SOFTWARE'}=~/IIS/; 174*0Sstevel@tonic-gate$IIS++ if defined($ENV{'SERVER_SOFTWARE'}) && $ENV{'SERVER_SOFTWARE'}=~/IIS/; 175*0Sstevel@tonic-gate 176*0Sstevel@tonic-gate# Turn on special checking for Doug MacEachern's modperl 177*0Sstevel@tonic-gateif (exists $ENV{MOD_PERL}) { 178*0Sstevel@tonic-gate eval "require mod_perl"; 179*0Sstevel@tonic-gate # mod_perl handlers may run system() on scripts using CGI.pm; 180*0Sstevel@tonic-gate # Make sure so we don't get fooled by inherited $ENV{MOD_PERL} 181*0Sstevel@tonic-gate if (defined $mod_perl::VERSION) { 182*0Sstevel@tonic-gate if ($mod_perl::VERSION >= 1.99) { 183*0Sstevel@tonic-gate $MOD_PERL = 2; 184*0Sstevel@tonic-gate require Apache::Response; 185*0Sstevel@tonic-gate require Apache::RequestRec; 186*0Sstevel@tonic-gate require Apache::RequestUtil; 187*0Sstevel@tonic-gate require APR::Pool; 188*0Sstevel@tonic-gate } else { 189*0Sstevel@tonic-gate $MOD_PERL = 1; 190*0Sstevel@tonic-gate require Apache; 191*0Sstevel@tonic-gate } 192*0Sstevel@tonic-gate } 193*0Sstevel@tonic-gate} 194*0Sstevel@tonic-gate 195*0Sstevel@tonic-gate# Turn on special checking for ActiveState's PerlEx 196*0Sstevel@tonic-gate$PERLEX++ if defined($ENV{'GATEWAY_INTERFACE'}) && $ENV{'GATEWAY_INTERFACE'} =~ /^CGI-PerlEx/; 197*0Sstevel@tonic-gate 198*0Sstevel@tonic-gate# Define the CRLF sequence. I can't use a simple "\r\n" because the meaning 199*0Sstevel@tonic-gate# of "\n" is different on different OS's (sometimes it generates CRLF, sometimes LF 200*0Sstevel@tonic-gate# and sometimes CR). The most popular VMS web server 201*0Sstevel@tonic-gate# doesn't accept CRLF -- instead it wants a LR. EBCDIC machines don't 202*0Sstevel@tonic-gate# use ASCII, so \015\012 means something different. I find this all 203*0Sstevel@tonic-gate# really annoying. 204*0Sstevel@tonic-gate$EBCDIC = "\t" ne "\011"; 205*0Sstevel@tonic-gateif ($OS eq 'VMS') { 206*0Sstevel@tonic-gate $CRLF = "\n"; 207*0Sstevel@tonic-gate} elsif ($EBCDIC) { 208*0Sstevel@tonic-gate $CRLF= "\r\n"; 209*0Sstevel@tonic-gate} else { 210*0Sstevel@tonic-gate $CRLF = "\015\012"; 211*0Sstevel@tonic-gate} 212*0Sstevel@tonic-gate 213*0Sstevel@tonic-gateif ($needs_binmode) { 214*0Sstevel@tonic-gate $CGI::DefaultClass->binmode(\*main::STDOUT); 215*0Sstevel@tonic-gate $CGI::DefaultClass->binmode(\*main::STDIN); 216*0Sstevel@tonic-gate $CGI::DefaultClass->binmode(\*main::STDERR); 217*0Sstevel@tonic-gate} 218*0Sstevel@tonic-gate 219*0Sstevel@tonic-gate%EXPORT_TAGS = ( 220*0Sstevel@tonic-gate ':html2'=>['h1'..'h6',qw/p br hr ol ul li dl dt dd menu code var strong em 221*0Sstevel@tonic-gate tt u i b blockquote pre img a address cite samp dfn html head 222*0Sstevel@tonic-gate base body Link nextid title meta kbd start_html end_html 223*0Sstevel@tonic-gate input Select option comment charset escapeHTML/], 224*0Sstevel@tonic-gate ':html3'=>[qw/div table caption th td TR Tr sup Sub strike applet Param 225*0Sstevel@tonic-gate embed basefont style span layer ilayer font frameset frame script small big Area Map/], 226*0Sstevel@tonic-gate ':html4'=>[qw/abbr acronym bdo col colgroup del fieldset iframe 227*0Sstevel@tonic-gate ins label legend noframes noscript object optgroup Q 228*0Sstevel@tonic-gate thead tbody tfoot/], 229*0Sstevel@tonic-gate ':netscape'=>[qw/blink fontsize center/], 230*0Sstevel@tonic-gate ':form'=>[qw/textfield textarea filefield password_field hidden checkbox checkbox_group 231*0Sstevel@tonic-gate submit reset defaults radio_group popup_menu button autoEscape 232*0Sstevel@tonic-gate scrolling_list image_button start_form end_form startform endform 233*0Sstevel@tonic-gate start_multipart_form end_multipart_form isindex tmpFileName uploadInfo URL_ENCODED MULTIPART/], 234*0Sstevel@tonic-gate ':cgi'=>[qw/param upload path_info path_translated url self_url script_name cookie Dump 235*0Sstevel@tonic-gate raw_cookie request_method query_string Accept user_agent remote_host content_type 236*0Sstevel@tonic-gate remote_addr referer server_name server_software server_port server_protocol virtual_port 237*0Sstevel@tonic-gate virtual_host remote_ident auth_type http append 238*0Sstevel@tonic-gate save_parameters restore_parameters param_fetch 239*0Sstevel@tonic-gate remote_user user_name header redirect import_names put 240*0Sstevel@tonic-gate Delete Delete_all url_param cgi_error/], 241*0Sstevel@tonic-gate ':ssl' => [qw/https/], 242*0Sstevel@tonic-gate ':cgi-lib' => [qw/ReadParse PrintHeader HtmlTop HtmlBot SplitParam Vars/], 243*0Sstevel@tonic-gate ':html' => [qw/:html2 :html3 :html4 :netscape/], 244*0Sstevel@tonic-gate ':standard' => [qw/:html2 :html3 :html4 :form :cgi/], 245*0Sstevel@tonic-gate ':push' => [qw/multipart_init multipart_start multipart_end multipart_final/], 246*0Sstevel@tonic-gate ':all' => [qw/:html2 :html3 :netscape :form :cgi :internal :html4/] 247*0Sstevel@tonic-gate ); 248*0Sstevel@tonic-gate 249*0Sstevel@tonic-gate# to import symbols into caller 250*0Sstevel@tonic-gatesub import { 251*0Sstevel@tonic-gate my $self = shift; 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gate # This causes modules to clash. 254*0Sstevel@tonic-gate undef %EXPORT_OK; 255*0Sstevel@tonic-gate undef %EXPORT; 256*0Sstevel@tonic-gate 257*0Sstevel@tonic-gate $self->_setup_symbols(@_); 258*0Sstevel@tonic-gate my ($callpack, $callfile, $callline) = caller; 259*0Sstevel@tonic-gate 260*0Sstevel@tonic-gate # To allow overriding, search through the packages 261*0Sstevel@tonic-gate # Till we find one in which the correct subroutine is defined. 262*0Sstevel@tonic-gate my @packages = ($self,@{"$self\:\:ISA"}); 263*0Sstevel@tonic-gate foreach $sym (keys %EXPORT) { 264*0Sstevel@tonic-gate my $pck; 265*0Sstevel@tonic-gate my $def = ${"$self\:\:AutoloadClass"} || $DefaultClass; 266*0Sstevel@tonic-gate foreach $pck (@packages) { 267*0Sstevel@tonic-gate if (defined(&{"$pck\:\:$sym"})) { 268*0Sstevel@tonic-gate $def = $pck; 269*0Sstevel@tonic-gate last; 270*0Sstevel@tonic-gate } 271*0Sstevel@tonic-gate } 272*0Sstevel@tonic-gate *{"${callpack}::$sym"} = \&{"$def\:\:$sym"}; 273*0Sstevel@tonic-gate } 274*0Sstevel@tonic-gate} 275*0Sstevel@tonic-gate 276*0Sstevel@tonic-gatesub compile { 277*0Sstevel@tonic-gate my $pack = shift; 278*0Sstevel@tonic-gate $pack->_setup_symbols('-compile',@_); 279*0Sstevel@tonic-gate} 280*0Sstevel@tonic-gate 281*0Sstevel@tonic-gatesub expand_tags { 282*0Sstevel@tonic-gate my($tag) = @_; 283*0Sstevel@tonic-gate return ("start_$1","end_$1") if $tag=~/^(?:\*|start_|end_)(.+)/; 284*0Sstevel@tonic-gate my(@r); 285*0Sstevel@tonic-gate return ($tag) unless $EXPORT_TAGS{$tag}; 286*0Sstevel@tonic-gate foreach (@{$EXPORT_TAGS{$tag}}) { 287*0Sstevel@tonic-gate push(@r,&expand_tags($_)); 288*0Sstevel@tonic-gate } 289*0Sstevel@tonic-gate return @r; 290*0Sstevel@tonic-gate} 291*0Sstevel@tonic-gate 292*0Sstevel@tonic-gate#### Method: new 293*0Sstevel@tonic-gate# The new routine. This will check the current environment 294*0Sstevel@tonic-gate# for an existing query string, and initialize itself, if so. 295*0Sstevel@tonic-gate#### 296*0Sstevel@tonic-gatesub new { 297*0Sstevel@tonic-gate my($class,@initializer) = @_; 298*0Sstevel@tonic-gate my $self = {}; 299*0Sstevel@tonic-gate 300*0Sstevel@tonic-gate bless $self,ref $class || $class || $DefaultClass; 301*0Sstevel@tonic-gate if (ref($initializer[0]) 302*0Sstevel@tonic-gate && (UNIVERSAL::isa($initializer[0],'Apache') 303*0Sstevel@tonic-gate || 304*0Sstevel@tonic-gate UNIVERSAL::isa($initializer[0],'Apache::RequestRec') 305*0Sstevel@tonic-gate )) { 306*0Sstevel@tonic-gate $self->r(shift @initializer); 307*0Sstevel@tonic-gate } 308*0Sstevel@tonic-gate if (ref($initializer[0]) 309*0Sstevel@tonic-gate && (UNIVERSAL::isa($initializer[0],'CODE'))) { 310*0Sstevel@tonic-gate $self->upload_hook(shift @initializer, shift @initializer); 311*0Sstevel@tonic-gate } 312*0Sstevel@tonic-gate if ($MOD_PERL) { 313*0Sstevel@tonic-gate $self->r(Apache->request) unless $self->r; 314*0Sstevel@tonic-gate my $r = $self->r; 315*0Sstevel@tonic-gate if ($MOD_PERL == 1) { 316*0Sstevel@tonic-gate $r->register_cleanup(\&CGI::_reset_globals); 317*0Sstevel@tonic-gate } 318*0Sstevel@tonic-gate else { 319*0Sstevel@tonic-gate # XXX: once we have the new API 320*0Sstevel@tonic-gate # will do a real PerlOptions -SetupEnv check 321*0Sstevel@tonic-gate $r->subprocess_env unless exists $ENV{REQUEST_METHOD}; 322*0Sstevel@tonic-gate $r->pool->cleanup_register(\&CGI::_reset_globals); 323*0Sstevel@tonic-gate } 324*0Sstevel@tonic-gate undef $NPH; 325*0Sstevel@tonic-gate } 326*0Sstevel@tonic-gate $self->_reset_globals if $PERLEX; 327*0Sstevel@tonic-gate $self->init(@initializer); 328*0Sstevel@tonic-gate return $self; 329*0Sstevel@tonic-gate} 330*0Sstevel@tonic-gate 331*0Sstevel@tonic-gate# We provide a DESTROY method so that we can ensure that 332*0Sstevel@tonic-gate# temporary files are closed (via Fh->DESTROY) before they 333*0Sstevel@tonic-gate# are unlinked (via CGITempFile->DESTROY) because it is not 334*0Sstevel@tonic-gate# possible to unlink an open file on Win32. We explicitly 335*0Sstevel@tonic-gate# call DESTROY on each, rather than just undefing them and 336*0Sstevel@tonic-gate# letting Perl DESTROY them by garbage collection, in case the 337*0Sstevel@tonic-gate# user is still holding any reference to them as well. 338*0Sstevel@tonic-gatesub DESTROY { 339*0Sstevel@tonic-gate my $self = shift; 340*0Sstevel@tonic-gate foreach my $href (values %{$self->{'.tmpfiles'}}) { 341*0Sstevel@tonic-gate $href->{hndl}->DESTROY if defined $href->{hndl}; 342*0Sstevel@tonic-gate $href->{name}->DESTROY if defined $href->{name}; 343*0Sstevel@tonic-gate } 344*0Sstevel@tonic-gate} 345*0Sstevel@tonic-gate 346*0Sstevel@tonic-gatesub r { 347*0Sstevel@tonic-gate my $self = shift; 348*0Sstevel@tonic-gate my $r = $self->{'.r'}; 349*0Sstevel@tonic-gate $self->{'.r'} = shift if @_; 350*0Sstevel@tonic-gate $r; 351*0Sstevel@tonic-gate} 352*0Sstevel@tonic-gate 353*0Sstevel@tonic-gatesub upload_hook { 354*0Sstevel@tonic-gate my ($self,$hook,$data) = self_or_default(@_); 355*0Sstevel@tonic-gate $self->{'.upload_hook'} = $hook; 356*0Sstevel@tonic-gate $self->{'.upload_data'} = $data; 357*0Sstevel@tonic-gate} 358*0Sstevel@tonic-gate 359*0Sstevel@tonic-gate#### Method: param 360*0Sstevel@tonic-gate# Returns the value(s)of a named parameter. 361*0Sstevel@tonic-gate# If invoked in a list context, returns the 362*0Sstevel@tonic-gate# entire list. Otherwise returns the first 363*0Sstevel@tonic-gate# member of the list. 364*0Sstevel@tonic-gate# If name is not provided, return a list of all 365*0Sstevel@tonic-gate# the known parameters names available. 366*0Sstevel@tonic-gate# If more than one argument is provided, the 367*0Sstevel@tonic-gate# second and subsequent arguments are used to 368*0Sstevel@tonic-gate# set the value of the parameter. 369*0Sstevel@tonic-gate#### 370*0Sstevel@tonic-gatesub param { 371*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 372*0Sstevel@tonic-gate return $self->all_parameters unless @p; 373*0Sstevel@tonic-gate my($name,$value,@other); 374*0Sstevel@tonic-gate 375*0Sstevel@tonic-gate # For compatibility between old calling style and use_named_parameters() style, 376*0Sstevel@tonic-gate # we have to special case for a single parameter present. 377*0Sstevel@tonic-gate if (@p > 1) { 378*0Sstevel@tonic-gate ($name,$value,@other) = rearrange([NAME,[DEFAULT,VALUE,VALUES]],@p); 379*0Sstevel@tonic-gate my(@values); 380*0Sstevel@tonic-gate 381*0Sstevel@tonic-gate if (substr($p[0],0,1) eq '-') { 382*0Sstevel@tonic-gate @values = defined($value) ? (ref($value) && ref($value) eq 'ARRAY' ? @{$value} : $value) : (); 383*0Sstevel@tonic-gate } else { 384*0Sstevel@tonic-gate foreach ($value,@other) { 385*0Sstevel@tonic-gate push(@values,$_) if defined($_); 386*0Sstevel@tonic-gate } 387*0Sstevel@tonic-gate } 388*0Sstevel@tonic-gate # If values is provided, then we set it. 389*0Sstevel@tonic-gate if (@values) { 390*0Sstevel@tonic-gate $self->add_parameter($name); 391*0Sstevel@tonic-gate $self->{$name}=[@values]; 392*0Sstevel@tonic-gate } 393*0Sstevel@tonic-gate } else { 394*0Sstevel@tonic-gate $name = $p[0]; 395*0Sstevel@tonic-gate } 396*0Sstevel@tonic-gate 397*0Sstevel@tonic-gate return unless defined($name) && $self->{$name}; 398*0Sstevel@tonic-gate return wantarray ? @{$self->{$name}} : $self->{$name}->[0]; 399*0Sstevel@tonic-gate} 400*0Sstevel@tonic-gate 401*0Sstevel@tonic-gatesub self_or_default { 402*0Sstevel@tonic-gate return @_ if defined($_[0]) && (!ref($_[0])) &&($_[0] eq 'CGI'); 403*0Sstevel@tonic-gate unless (defined($_[0]) && 404*0Sstevel@tonic-gate (ref($_[0]) eq 'CGI' || UNIVERSAL::isa($_[0],'CGI')) # slightly optimized for common case 405*0Sstevel@tonic-gate ) { 406*0Sstevel@tonic-gate $Q = $CGI::DefaultClass->new unless defined($Q); 407*0Sstevel@tonic-gate unshift(@_,$Q); 408*0Sstevel@tonic-gate } 409*0Sstevel@tonic-gate return wantarray ? @_ : $Q; 410*0Sstevel@tonic-gate} 411*0Sstevel@tonic-gate 412*0Sstevel@tonic-gatesub self_or_CGI { 413*0Sstevel@tonic-gate local $^W=0; # prevent a warning 414*0Sstevel@tonic-gate if (defined($_[0]) && 415*0Sstevel@tonic-gate (substr(ref($_[0]),0,3) eq 'CGI' 416*0Sstevel@tonic-gate || UNIVERSAL::isa($_[0],'CGI'))) { 417*0Sstevel@tonic-gate return @_; 418*0Sstevel@tonic-gate } else { 419*0Sstevel@tonic-gate return ($DefaultClass,@_); 420*0Sstevel@tonic-gate } 421*0Sstevel@tonic-gate} 422*0Sstevel@tonic-gate 423*0Sstevel@tonic-gate######################################## 424*0Sstevel@tonic-gate# THESE METHODS ARE MORE OR LESS PRIVATE 425*0Sstevel@tonic-gate# GO TO THE __DATA__ SECTION TO SEE MORE 426*0Sstevel@tonic-gate# PUBLIC METHODS 427*0Sstevel@tonic-gate######################################## 428*0Sstevel@tonic-gate 429*0Sstevel@tonic-gate# Initialize the query object from the environment. 430*0Sstevel@tonic-gate# If a parameter list is found, this object will be set 431*0Sstevel@tonic-gate# to an associative array in which parameter names are keys 432*0Sstevel@tonic-gate# and the values are stored as lists 433*0Sstevel@tonic-gate# If a keyword list is found, this method creates a bogus 434*0Sstevel@tonic-gate# parameter list with the single parameter 'keywords'. 435*0Sstevel@tonic-gate 436*0Sstevel@tonic-gatesub init { 437*0Sstevel@tonic-gate my $self = shift; 438*0Sstevel@tonic-gate my($query_string,$meth,$content_length,$fh,@lines) = ('','','',''); 439*0Sstevel@tonic-gate 440*0Sstevel@tonic-gate my $initializer = shift; # for backward compatibility 441*0Sstevel@tonic-gate local($/) = "\n"; 442*0Sstevel@tonic-gate 443*0Sstevel@tonic-gate # set autoescaping on by default 444*0Sstevel@tonic-gate $self->{'escape'} = 1; 445*0Sstevel@tonic-gate 446*0Sstevel@tonic-gate # if we get called more than once, we want to initialize 447*0Sstevel@tonic-gate # ourselves from the original query (which may be gone 448*0Sstevel@tonic-gate # if it was read from STDIN originally.) 449*0Sstevel@tonic-gate if (defined(@QUERY_PARAM) && !defined($initializer)) { 450*0Sstevel@tonic-gate foreach (@QUERY_PARAM) { 451*0Sstevel@tonic-gate $self->param('-name'=>$_,'-value'=>$QUERY_PARAM{$_}); 452*0Sstevel@tonic-gate } 453*0Sstevel@tonic-gate $self->charset($QUERY_CHARSET); 454*0Sstevel@tonic-gate $self->{'.fieldnames'} = {%QUERY_FIELDNAMES}; 455*0Sstevel@tonic-gate return; 456*0Sstevel@tonic-gate } 457*0Sstevel@tonic-gate 458*0Sstevel@tonic-gate $meth=$ENV{'REQUEST_METHOD'} if defined($ENV{'REQUEST_METHOD'}); 459*0Sstevel@tonic-gate $content_length = defined($ENV{'CONTENT_LENGTH'}) ? $ENV{'CONTENT_LENGTH'} : 0; 460*0Sstevel@tonic-gate 461*0Sstevel@tonic-gate $fh = to_filehandle($initializer) if $initializer; 462*0Sstevel@tonic-gate 463*0Sstevel@tonic-gate # set charset to the safe ISO-8859-1 464*0Sstevel@tonic-gate $self->charset('ISO-8859-1'); 465*0Sstevel@tonic-gate 466*0Sstevel@tonic-gate METHOD: { 467*0Sstevel@tonic-gate 468*0Sstevel@tonic-gate # avoid unreasonably large postings 469*0Sstevel@tonic-gate if (($POST_MAX > 0) && ($content_length > $POST_MAX)) { 470*0Sstevel@tonic-gate # quietly read and discard the post 471*0Sstevel@tonic-gate my $buffer; 472*0Sstevel@tonic-gate my $max = $content_length; 473*0Sstevel@tonic-gate while ($max > 0 && 474*0Sstevel@tonic-gate (my $bytes = $MOD_PERL 475*0Sstevel@tonic-gate ? $self->r->read($buffer,$max < 10000 ? $max : 10000) 476*0Sstevel@tonic-gate : read(STDIN,$buffer,$max < 10000 ? $max : 10000) 477*0Sstevel@tonic-gate )) { 478*0Sstevel@tonic-gate $self->cgi_error("413 Request entity too large"); 479*0Sstevel@tonic-gate last METHOD; 480*0Sstevel@tonic-gate } 481*0Sstevel@tonic-gate } 482*0Sstevel@tonic-gate 483*0Sstevel@tonic-gate # Process multipart postings, but only if the initializer is 484*0Sstevel@tonic-gate # not defined. 485*0Sstevel@tonic-gate if ($meth eq 'POST' 486*0Sstevel@tonic-gate && defined($ENV{'CONTENT_TYPE'}) 487*0Sstevel@tonic-gate && $ENV{'CONTENT_TYPE'}=~m|^multipart/form-data| 488*0Sstevel@tonic-gate && !defined($initializer) 489*0Sstevel@tonic-gate ) { 490*0Sstevel@tonic-gate my($boundary) = $ENV{'CONTENT_TYPE'} =~ /boundary=\"?([^\";,]+)\"?/; 491*0Sstevel@tonic-gate $self->read_multipart($boundary,$content_length); 492*0Sstevel@tonic-gate last METHOD; 493*0Sstevel@tonic-gate } 494*0Sstevel@tonic-gate 495*0Sstevel@tonic-gate # If initializer is defined, then read parameters 496*0Sstevel@tonic-gate # from it. 497*0Sstevel@tonic-gate if (defined($initializer)) { 498*0Sstevel@tonic-gate if (UNIVERSAL::isa($initializer,'CGI')) { 499*0Sstevel@tonic-gate $query_string = $initializer->query_string; 500*0Sstevel@tonic-gate last METHOD; 501*0Sstevel@tonic-gate } 502*0Sstevel@tonic-gate if (ref($initializer) && ref($initializer) eq 'HASH') { 503*0Sstevel@tonic-gate foreach (keys %$initializer) { 504*0Sstevel@tonic-gate $self->param('-name'=>$_,'-value'=>$initializer->{$_}); 505*0Sstevel@tonic-gate } 506*0Sstevel@tonic-gate last METHOD; 507*0Sstevel@tonic-gate } 508*0Sstevel@tonic-gate 509*0Sstevel@tonic-gate if (defined($fh) && ($fh ne '')) { 510*0Sstevel@tonic-gate while (<$fh>) { 511*0Sstevel@tonic-gate chomp; 512*0Sstevel@tonic-gate last if /^=/; 513*0Sstevel@tonic-gate push(@lines,$_); 514*0Sstevel@tonic-gate } 515*0Sstevel@tonic-gate # massage back into standard format 516*0Sstevel@tonic-gate if ("@lines" =~ /=/) { 517*0Sstevel@tonic-gate $query_string=join("&",@lines); 518*0Sstevel@tonic-gate } else { 519*0Sstevel@tonic-gate $query_string=join("+",@lines); 520*0Sstevel@tonic-gate } 521*0Sstevel@tonic-gate last METHOD; 522*0Sstevel@tonic-gate } 523*0Sstevel@tonic-gate 524*0Sstevel@tonic-gate if (defined($fh) && ($fh ne '')) { 525*0Sstevel@tonic-gate while (<$fh>) { 526*0Sstevel@tonic-gate chomp; 527*0Sstevel@tonic-gate last if /^=/; 528*0Sstevel@tonic-gate push(@lines,$_); 529*0Sstevel@tonic-gate } 530*0Sstevel@tonic-gate # massage back into standard format 531*0Sstevel@tonic-gate if ("@lines" =~ /=/) { 532*0Sstevel@tonic-gate $query_string=join("&",@lines); 533*0Sstevel@tonic-gate } else { 534*0Sstevel@tonic-gate $query_string=join("+",@lines); 535*0Sstevel@tonic-gate } 536*0Sstevel@tonic-gate last METHOD; 537*0Sstevel@tonic-gate } 538*0Sstevel@tonic-gate 539*0Sstevel@tonic-gate # last chance -- treat it as a string 540*0Sstevel@tonic-gate $initializer = $$initializer if ref($initializer) eq 'SCALAR'; 541*0Sstevel@tonic-gate $query_string = $initializer; 542*0Sstevel@tonic-gate 543*0Sstevel@tonic-gate last METHOD; 544*0Sstevel@tonic-gate } 545*0Sstevel@tonic-gate 546*0Sstevel@tonic-gate # If method is GET or HEAD, fetch the query from 547*0Sstevel@tonic-gate # the environment. 548*0Sstevel@tonic-gate if ($meth=~/^(GET|HEAD)$/) { 549*0Sstevel@tonic-gate if ($MOD_PERL) { 550*0Sstevel@tonic-gate $query_string = $self->r->args; 551*0Sstevel@tonic-gate } else { 552*0Sstevel@tonic-gate $query_string = $ENV{'QUERY_STRING'} if defined $ENV{'QUERY_STRING'}; 553*0Sstevel@tonic-gate $query_string ||= $ENV{'REDIRECT_QUERY_STRING'} if defined $ENV{'REDIRECT_QUERY_STRING'}; 554*0Sstevel@tonic-gate } 555*0Sstevel@tonic-gate last METHOD; 556*0Sstevel@tonic-gate } 557*0Sstevel@tonic-gate 558*0Sstevel@tonic-gate if ($meth eq 'POST') { 559*0Sstevel@tonic-gate $self->read_from_client(\$query_string,$content_length,0) 560*0Sstevel@tonic-gate if $content_length > 0; 561*0Sstevel@tonic-gate # Some people want to have their cake and eat it too! 562*0Sstevel@tonic-gate # Uncomment this line to have the contents of the query string 563*0Sstevel@tonic-gate # APPENDED to the POST data. 564*0Sstevel@tonic-gate # $query_string .= (length($query_string) ? '&' : '') . $ENV{'QUERY_STRING'} if defined $ENV{'QUERY_STRING'}; 565*0Sstevel@tonic-gate last METHOD; 566*0Sstevel@tonic-gate } 567*0Sstevel@tonic-gate 568*0Sstevel@tonic-gate # If $meth is not of GET, POST or HEAD, assume we're being debugged offline. 569*0Sstevel@tonic-gate # Check the command line and then the standard input for data. 570*0Sstevel@tonic-gate # We use the shellwords package in order to behave the way that 571*0Sstevel@tonic-gate # UN*X programmers expect. 572*0Sstevel@tonic-gate if ($DEBUG) 573*0Sstevel@tonic-gate { 574*0Sstevel@tonic-gate my $cmdline_ret = read_from_cmdline(); 575*0Sstevel@tonic-gate $query_string = $cmdline_ret->{'query_string'}; 576*0Sstevel@tonic-gate if (defined($cmdline_ret->{'subpath'})) 577*0Sstevel@tonic-gate { 578*0Sstevel@tonic-gate $self->path_info($cmdline_ret->{'subpath'}); 579*0Sstevel@tonic-gate } 580*0Sstevel@tonic-gate } 581*0Sstevel@tonic-gate } 582*0Sstevel@tonic-gate 583*0Sstevel@tonic-gate# YL: Begin Change for XML handler 10/19/2001 584*0Sstevel@tonic-gate if ($meth eq 'POST' 585*0Sstevel@tonic-gate && defined($ENV{'CONTENT_TYPE'}) 586*0Sstevel@tonic-gate && $ENV{'CONTENT_TYPE'} !~ m|^application/x-www-form-urlencoded| 587*0Sstevel@tonic-gate && $ENV{'CONTENT_TYPE'} !~ m|^multipart/form-data| ) { 588*0Sstevel@tonic-gate my($param) = 'POSTDATA' ; 589*0Sstevel@tonic-gate $self->add_parameter($param) ; 590*0Sstevel@tonic-gate push (@{$self->{$param}},$query_string); 591*0Sstevel@tonic-gate undef $query_string ; 592*0Sstevel@tonic-gate } 593*0Sstevel@tonic-gate# YL: End Change for XML handler 10/19/2001 594*0Sstevel@tonic-gate 595*0Sstevel@tonic-gate # We now have the query string in hand. We do slightly 596*0Sstevel@tonic-gate # different things for keyword lists and parameter lists. 597*0Sstevel@tonic-gate if (defined $query_string && length $query_string) { 598*0Sstevel@tonic-gate if ($query_string =~ /[&=;]/) { 599*0Sstevel@tonic-gate $self->parse_params($query_string); 600*0Sstevel@tonic-gate } else { 601*0Sstevel@tonic-gate $self->add_parameter('keywords'); 602*0Sstevel@tonic-gate $self->{'keywords'} = [$self->parse_keywordlist($query_string)]; 603*0Sstevel@tonic-gate } 604*0Sstevel@tonic-gate } 605*0Sstevel@tonic-gate 606*0Sstevel@tonic-gate # Special case. Erase everything if there is a field named 607*0Sstevel@tonic-gate # .defaults. 608*0Sstevel@tonic-gate if ($self->param('.defaults')) { 609*0Sstevel@tonic-gate $self->delete_all(); 610*0Sstevel@tonic-gate } 611*0Sstevel@tonic-gate 612*0Sstevel@tonic-gate # Associative array containing our defined fieldnames 613*0Sstevel@tonic-gate $self->{'.fieldnames'} = {}; 614*0Sstevel@tonic-gate foreach ($self->param('.cgifields')) { 615*0Sstevel@tonic-gate $self->{'.fieldnames'}->{$_}++; 616*0Sstevel@tonic-gate } 617*0Sstevel@tonic-gate 618*0Sstevel@tonic-gate # Clear out our default submission button flag if present 619*0Sstevel@tonic-gate $self->delete('.submit'); 620*0Sstevel@tonic-gate $self->delete('.cgifields'); 621*0Sstevel@tonic-gate 622*0Sstevel@tonic-gate $self->save_request unless defined $initializer; 623*0Sstevel@tonic-gate} 624*0Sstevel@tonic-gate 625*0Sstevel@tonic-gate# FUNCTIONS TO OVERRIDE: 626*0Sstevel@tonic-gate# Turn a string into a filehandle 627*0Sstevel@tonic-gatesub to_filehandle { 628*0Sstevel@tonic-gate my $thingy = shift; 629*0Sstevel@tonic-gate return undef unless $thingy; 630*0Sstevel@tonic-gate return $thingy if UNIVERSAL::isa($thingy,'GLOB'); 631*0Sstevel@tonic-gate return $thingy if UNIVERSAL::isa($thingy,'FileHandle'); 632*0Sstevel@tonic-gate if (!ref($thingy)) { 633*0Sstevel@tonic-gate my $caller = 1; 634*0Sstevel@tonic-gate while (my $package = caller($caller++)) { 635*0Sstevel@tonic-gate my($tmp) = $thingy=~/[\':]/ ? $thingy : "$package\:\:$thingy"; 636*0Sstevel@tonic-gate return $tmp if defined(fileno($tmp)); 637*0Sstevel@tonic-gate } 638*0Sstevel@tonic-gate } 639*0Sstevel@tonic-gate return undef; 640*0Sstevel@tonic-gate} 641*0Sstevel@tonic-gate 642*0Sstevel@tonic-gate# send output to the browser 643*0Sstevel@tonic-gatesub put { 644*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 645*0Sstevel@tonic-gate $self->print(@p); 646*0Sstevel@tonic-gate} 647*0Sstevel@tonic-gate 648*0Sstevel@tonic-gate# print to standard output (for overriding in mod_perl) 649*0Sstevel@tonic-gatesub print { 650*0Sstevel@tonic-gate shift; 651*0Sstevel@tonic-gate CORE::print(@_); 652*0Sstevel@tonic-gate} 653*0Sstevel@tonic-gate 654*0Sstevel@tonic-gate# get/set last cgi_error 655*0Sstevel@tonic-gatesub cgi_error { 656*0Sstevel@tonic-gate my ($self,$err) = self_or_default(@_); 657*0Sstevel@tonic-gate $self->{'.cgi_error'} = $err if defined $err; 658*0Sstevel@tonic-gate return $self->{'.cgi_error'}; 659*0Sstevel@tonic-gate} 660*0Sstevel@tonic-gate 661*0Sstevel@tonic-gatesub save_request { 662*0Sstevel@tonic-gate my($self) = @_; 663*0Sstevel@tonic-gate # We're going to play with the package globals now so that if we get called 664*0Sstevel@tonic-gate # again, we initialize ourselves in exactly the same way. This allows 665*0Sstevel@tonic-gate # us to have several of these objects. 666*0Sstevel@tonic-gate @QUERY_PARAM = $self->param; # save list of parameters 667*0Sstevel@tonic-gate foreach (@QUERY_PARAM) { 668*0Sstevel@tonic-gate next unless defined $_; 669*0Sstevel@tonic-gate $QUERY_PARAM{$_}=$self->{$_}; 670*0Sstevel@tonic-gate } 671*0Sstevel@tonic-gate $QUERY_CHARSET = $self->charset; 672*0Sstevel@tonic-gate %QUERY_FIELDNAMES = %{$self->{'.fieldnames'}}; 673*0Sstevel@tonic-gate} 674*0Sstevel@tonic-gate 675*0Sstevel@tonic-gatesub parse_params { 676*0Sstevel@tonic-gate my($self,$tosplit) = @_; 677*0Sstevel@tonic-gate my(@pairs) = split(/[&;]/,$tosplit); 678*0Sstevel@tonic-gate my($param,$value); 679*0Sstevel@tonic-gate foreach (@pairs) { 680*0Sstevel@tonic-gate ($param,$value) = split('=',$_,2); 681*0Sstevel@tonic-gate next unless defined $param; 682*0Sstevel@tonic-gate next if $NO_UNDEF_PARAMS and not defined $value; 683*0Sstevel@tonic-gate $value = '' unless defined $value; 684*0Sstevel@tonic-gate $param = unescape($param); 685*0Sstevel@tonic-gate $value = unescape($value); 686*0Sstevel@tonic-gate $self->add_parameter($param); 687*0Sstevel@tonic-gate push (@{$self->{$param}},$value); 688*0Sstevel@tonic-gate } 689*0Sstevel@tonic-gate} 690*0Sstevel@tonic-gate 691*0Sstevel@tonic-gatesub add_parameter { 692*0Sstevel@tonic-gate my($self,$param)=@_; 693*0Sstevel@tonic-gate return unless defined $param; 694*0Sstevel@tonic-gate push (@{$self->{'.parameters'}},$param) 695*0Sstevel@tonic-gate unless defined($self->{$param}); 696*0Sstevel@tonic-gate} 697*0Sstevel@tonic-gate 698*0Sstevel@tonic-gatesub all_parameters { 699*0Sstevel@tonic-gate my $self = shift; 700*0Sstevel@tonic-gate return () unless defined($self) && $self->{'.parameters'}; 701*0Sstevel@tonic-gate return () unless @{$self->{'.parameters'}}; 702*0Sstevel@tonic-gate return @{$self->{'.parameters'}}; 703*0Sstevel@tonic-gate} 704*0Sstevel@tonic-gate 705*0Sstevel@tonic-gate# put a filehandle into binary mode (DOS) 706*0Sstevel@tonic-gatesub binmode { 707*0Sstevel@tonic-gate return unless defined($_[1]) && defined fileno($_[1]); 708*0Sstevel@tonic-gate CORE::binmode($_[1]); 709*0Sstevel@tonic-gate} 710*0Sstevel@tonic-gate 711*0Sstevel@tonic-gatesub _make_tag_func { 712*0Sstevel@tonic-gate my ($self,$tagname) = @_; 713*0Sstevel@tonic-gate my $func = qq( 714*0Sstevel@tonic-gate sub $tagname { 715*0Sstevel@tonic-gate my (\$q,\$a,\@rest) = self_or_default(\@_); 716*0Sstevel@tonic-gate my(\$attr) = ''; 717*0Sstevel@tonic-gate if (ref(\$a) && ref(\$a) eq 'HASH') { 718*0Sstevel@tonic-gate my(\@attr) = make_attributes(\$a,\$q->{'escape'}); 719*0Sstevel@tonic-gate \$attr = " \@attr" if \@attr; 720*0Sstevel@tonic-gate } else { 721*0Sstevel@tonic-gate unshift \@rest,\$a if defined \$a; 722*0Sstevel@tonic-gate } 723*0Sstevel@tonic-gate ); 724*0Sstevel@tonic-gate if ($tagname=~/start_(\w+)/i) { 725*0Sstevel@tonic-gate $func .= qq! return "<\L$1\E\$attr>";} !; 726*0Sstevel@tonic-gate } elsif ($tagname=~/end_(\w+)/i) { 727*0Sstevel@tonic-gate $func .= qq! return "<\L/$1\E>"; } !; 728*0Sstevel@tonic-gate } else { 729*0Sstevel@tonic-gate $func .= qq# 730*0Sstevel@tonic-gate return \$XHTML ? "\L<$tagname\E\$attr />" : "\L<$tagname\E\$attr>" unless \@rest; 731*0Sstevel@tonic-gate my(\$tag,\$untag) = ("\L<$tagname\E\$attr>","\L</$tagname>\E"); 732*0Sstevel@tonic-gate my \@result = map { "\$tag\$_\$untag" } 733*0Sstevel@tonic-gate (ref(\$rest[0]) eq 'ARRAY') ? \@{\$rest[0]} : "\@rest"; 734*0Sstevel@tonic-gate return "\@result"; 735*0Sstevel@tonic-gate }#; 736*0Sstevel@tonic-gate } 737*0Sstevel@tonic-gatereturn $func; 738*0Sstevel@tonic-gate} 739*0Sstevel@tonic-gate 740*0Sstevel@tonic-gatesub AUTOLOAD { 741*0Sstevel@tonic-gate print STDERR "CGI::AUTOLOAD for $AUTOLOAD\n" if $CGI::AUTOLOAD_DEBUG; 742*0Sstevel@tonic-gate my $func = &_compile; 743*0Sstevel@tonic-gate goto &$func; 744*0Sstevel@tonic-gate} 745*0Sstevel@tonic-gate 746*0Sstevel@tonic-gatesub _compile { 747*0Sstevel@tonic-gate my($func) = $AUTOLOAD; 748*0Sstevel@tonic-gate my($pack,$func_name); 749*0Sstevel@tonic-gate { 750*0Sstevel@tonic-gate local($1,$2); # this fixes an obscure variable suicide problem. 751*0Sstevel@tonic-gate $func=~/(.+)::([^:]+)$/; 752*0Sstevel@tonic-gate ($pack,$func_name) = ($1,$2); 753*0Sstevel@tonic-gate $pack=~s/::SUPER$//; # fix another obscure problem 754*0Sstevel@tonic-gate $pack = ${"$pack\:\:AutoloadClass"} || $CGI::DefaultClass 755*0Sstevel@tonic-gate unless defined(${"$pack\:\:AUTOLOADED_ROUTINES"}); 756*0Sstevel@tonic-gate 757*0Sstevel@tonic-gate my($sub) = \%{"$pack\:\:SUBS"}; 758*0Sstevel@tonic-gate unless (%$sub) { 759*0Sstevel@tonic-gate my($auto) = \${"$pack\:\:AUTOLOADED_ROUTINES"}; 760*0Sstevel@tonic-gate eval "package $pack; $$auto"; 761*0Sstevel@tonic-gate croak("$AUTOLOAD: $@") if $@; 762*0Sstevel@tonic-gate $$auto = ''; # Free the unneeded storage (but don't undef it!!!) 763*0Sstevel@tonic-gate } 764*0Sstevel@tonic-gate my($code) = $sub->{$func_name}; 765*0Sstevel@tonic-gate 766*0Sstevel@tonic-gate $code = "sub $AUTOLOAD { }" if (!$code and $func_name eq 'DESTROY'); 767*0Sstevel@tonic-gate if (!$code) { 768*0Sstevel@tonic-gate (my $base = $func_name) =~ s/^(start_|end_)//i; 769*0Sstevel@tonic-gate if ($EXPORT{':any'} || 770*0Sstevel@tonic-gate $EXPORT{'-any'} || 771*0Sstevel@tonic-gate $EXPORT{$base} || 772*0Sstevel@tonic-gate (%EXPORT_OK || grep(++$EXPORT_OK{$_},&expand_tags(':html'))) 773*0Sstevel@tonic-gate && $EXPORT_OK{$base}) { 774*0Sstevel@tonic-gate $code = $CGI::DefaultClass->_make_tag_func($func_name); 775*0Sstevel@tonic-gate } 776*0Sstevel@tonic-gate } 777*0Sstevel@tonic-gate croak("Undefined subroutine $AUTOLOAD\n") unless $code; 778*0Sstevel@tonic-gate eval "package $pack; $code"; 779*0Sstevel@tonic-gate if ($@) { 780*0Sstevel@tonic-gate $@ =~ s/ at .*\n//; 781*0Sstevel@tonic-gate croak("$AUTOLOAD: $@"); 782*0Sstevel@tonic-gate } 783*0Sstevel@tonic-gate } 784*0Sstevel@tonic-gate CORE::delete($sub->{$func_name}); #free storage 785*0Sstevel@tonic-gate return "$pack\:\:$func_name"; 786*0Sstevel@tonic-gate} 787*0Sstevel@tonic-gate 788*0Sstevel@tonic-gatesub _selected { 789*0Sstevel@tonic-gate my $self = shift; 790*0Sstevel@tonic-gate my $value = shift; 791*0Sstevel@tonic-gate return '' unless $value; 792*0Sstevel@tonic-gate return $XHTML ? qq( selected="selected") : qq( selected); 793*0Sstevel@tonic-gate} 794*0Sstevel@tonic-gate 795*0Sstevel@tonic-gatesub _checked { 796*0Sstevel@tonic-gate my $self = shift; 797*0Sstevel@tonic-gate my $value = shift; 798*0Sstevel@tonic-gate return '' unless $value; 799*0Sstevel@tonic-gate return $XHTML ? qq( checked="checked") : qq( checked); 800*0Sstevel@tonic-gate} 801*0Sstevel@tonic-gate 802*0Sstevel@tonic-gatesub _reset_globals { initialize_globals(); } 803*0Sstevel@tonic-gate 804*0Sstevel@tonic-gatesub _setup_symbols { 805*0Sstevel@tonic-gate my $self = shift; 806*0Sstevel@tonic-gate my $compile = 0; 807*0Sstevel@tonic-gate 808*0Sstevel@tonic-gate # to avoid reexporting unwanted variables 809*0Sstevel@tonic-gate undef %EXPORT; 810*0Sstevel@tonic-gate 811*0Sstevel@tonic-gate foreach (@_) { 812*0Sstevel@tonic-gate $HEADERS_ONCE++, next if /^[:-]unique_headers$/; 813*0Sstevel@tonic-gate $NPH++, next if /^[:-]nph$/; 814*0Sstevel@tonic-gate $NOSTICKY++, next if /^[:-]nosticky$/; 815*0Sstevel@tonic-gate $DEBUG=0, next if /^[:-]no_?[Dd]ebug$/; 816*0Sstevel@tonic-gate $DEBUG=2, next if /^[:-][Dd]ebug$/; 817*0Sstevel@tonic-gate $USE_PARAM_SEMICOLONS++, next if /^[:-]newstyle_urls$/; 818*0Sstevel@tonic-gate $XHTML++, next if /^[:-]xhtml$/; 819*0Sstevel@tonic-gate $XHTML=0, next if /^[:-]no_?xhtml$/; 820*0Sstevel@tonic-gate $USE_PARAM_SEMICOLONS=0, next if /^[:-]oldstyle_urls$/; 821*0Sstevel@tonic-gate $PRIVATE_TEMPFILES++, next if /^[:-]private_tempfiles$/; 822*0Sstevel@tonic-gate $CLOSE_UPLOAD_FILES++, next if /^[:-]close_upload_files$/; 823*0Sstevel@tonic-gate $EXPORT{$_}++, next if /^[:-]any$/; 824*0Sstevel@tonic-gate $compile++, next if /^[:-]compile$/; 825*0Sstevel@tonic-gate $NO_UNDEF_PARAMS++, next if /^[:-]no_undef_params$/; 826*0Sstevel@tonic-gate 827*0Sstevel@tonic-gate # This is probably extremely evil code -- to be deleted some day. 828*0Sstevel@tonic-gate if (/^[-]autoload$/) { 829*0Sstevel@tonic-gate my($pkg) = caller(1); 830*0Sstevel@tonic-gate *{"${pkg}::AUTOLOAD"} = sub { 831*0Sstevel@tonic-gate my($routine) = $AUTOLOAD; 832*0Sstevel@tonic-gate $routine =~ s/^.*::/CGI::/; 833*0Sstevel@tonic-gate &$routine; 834*0Sstevel@tonic-gate }; 835*0Sstevel@tonic-gate next; 836*0Sstevel@tonic-gate } 837*0Sstevel@tonic-gate 838*0Sstevel@tonic-gate foreach (&expand_tags($_)) { 839*0Sstevel@tonic-gate tr/a-zA-Z0-9_//cd; # don't allow weird function names 840*0Sstevel@tonic-gate $EXPORT{$_}++; 841*0Sstevel@tonic-gate } 842*0Sstevel@tonic-gate } 843*0Sstevel@tonic-gate _compile_all(keys %EXPORT) if $compile; 844*0Sstevel@tonic-gate @SAVED_SYMBOLS = @_; 845*0Sstevel@tonic-gate} 846*0Sstevel@tonic-gate 847*0Sstevel@tonic-gatesub charset { 848*0Sstevel@tonic-gate my ($self,$charset) = self_or_default(@_); 849*0Sstevel@tonic-gate $self->{'.charset'} = $charset if defined $charset; 850*0Sstevel@tonic-gate $self->{'.charset'}; 851*0Sstevel@tonic-gate} 852*0Sstevel@tonic-gate 853*0Sstevel@tonic-gate############################################################################### 854*0Sstevel@tonic-gate################# THESE FUNCTIONS ARE AUTOLOADED ON DEMAND #################### 855*0Sstevel@tonic-gate############################################################################### 856*0Sstevel@tonic-gate$AUTOLOADED_ROUTINES = ''; # get rid of -w warning 857*0Sstevel@tonic-gate$AUTOLOADED_ROUTINES=<<'END_OF_AUTOLOAD'; 858*0Sstevel@tonic-gate 859*0Sstevel@tonic-gate%SUBS = ( 860*0Sstevel@tonic-gate 861*0Sstevel@tonic-gate'URL_ENCODED'=> <<'END_OF_FUNC', 862*0Sstevel@tonic-gatesub URL_ENCODED { 'application/x-www-form-urlencoded'; } 863*0Sstevel@tonic-gateEND_OF_FUNC 864*0Sstevel@tonic-gate 865*0Sstevel@tonic-gate'MULTIPART' => <<'END_OF_FUNC', 866*0Sstevel@tonic-gatesub MULTIPART { 'multipart/form-data'; } 867*0Sstevel@tonic-gateEND_OF_FUNC 868*0Sstevel@tonic-gate 869*0Sstevel@tonic-gate'SERVER_PUSH' => <<'END_OF_FUNC', 870*0Sstevel@tonic-gatesub SERVER_PUSH { 'multipart/x-mixed-replace;boundary="' . shift() . '"'; } 871*0Sstevel@tonic-gateEND_OF_FUNC 872*0Sstevel@tonic-gate 873*0Sstevel@tonic-gate'new_MultipartBuffer' => <<'END_OF_FUNC', 874*0Sstevel@tonic-gate# Create a new multipart buffer 875*0Sstevel@tonic-gatesub new_MultipartBuffer { 876*0Sstevel@tonic-gate my($self,$boundary,$length) = @_; 877*0Sstevel@tonic-gate return MultipartBuffer->new($self,$boundary,$length); 878*0Sstevel@tonic-gate} 879*0Sstevel@tonic-gateEND_OF_FUNC 880*0Sstevel@tonic-gate 881*0Sstevel@tonic-gate'read_from_client' => <<'END_OF_FUNC', 882*0Sstevel@tonic-gate# Read data from a file handle 883*0Sstevel@tonic-gatesub read_from_client { 884*0Sstevel@tonic-gate my($self, $buff, $len, $offset) = @_; 885*0Sstevel@tonic-gate local $^W=0; # prevent a warning 886*0Sstevel@tonic-gate return $MOD_PERL 887*0Sstevel@tonic-gate ? $self->r->read($$buff, $len, $offset) 888*0Sstevel@tonic-gate : read(\*STDIN, $$buff, $len, $offset); 889*0Sstevel@tonic-gate} 890*0Sstevel@tonic-gateEND_OF_FUNC 891*0Sstevel@tonic-gate 892*0Sstevel@tonic-gate'delete' => <<'END_OF_FUNC', 893*0Sstevel@tonic-gate#### Method: delete 894*0Sstevel@tonic-gate# Deletes the named parameter entirely. 895*0Sstevel@tonic-gate#### 896*0Sstevel@tonic-gatesub delete { 897*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 898*0Sstevel@tonic-gate my(@names) = rearrange([NAME],@p); 899*0Sstevel@tonic-gate my @to_delete = ref($names[0]) eq 'ARRAY' ? @$names[0] : @names; 900*0Sstevel@tonic-gate my %to_delete; 901*0Sstevel@tonic-gate foreach my $name (@to_delete) 902*0Sstevel@tonic-gate { 903*0Sstevel@tonic-gate CORE::delete $self->{$name}; 904*0Sstevel@tonic-gate CORE::delete $self->{'.fieldnames'}->{$name}; 905*0Sstevel@tonic-gate $to_delete{$name}++; 906*0Sstevel@tonic-gate } 907*0Sstevel@tonic-gate @{$self->{'.parameters'}}=grep { !exists($to_delete{$_}) } $self->param(); 908*0Sstevel@tonic-gate return wantarray ? () : undef; 909*0Sstevel@tonic-gate} 910*0Sstevel@tonic-gateEND_OF_FUNC 911*0Sstevel@tonic-gate 912*0Sstevel@tonic-gate#### Method: import_names 913*0Sstevel@tonic-gate# Import all parameters into the given namespace. 914*0Sstevel@tonic-gate# Assumes namespace 'Q' if not specified 915*0Sstevel@tonic-gate#### 916*0Sstevel@tonic-gate'import_names' => <<'END_OF_FUNC', 917*0Sstevel@tonic-gatesub import_names { 918*0Sstevel@tonic-gate my($self,$namespace,$delete) = self_or_default(@_); 919*0Sstevel@tonic-gate $namespace = 'Q' unless defined($namespace); 920*0Sstevel@tonic-gate die "Can't import names into \"main\"\n" if \%{"${namespace}::"} == \%::; 921*0Sstevel@tonic-gate if ($delete || $MOD_PERL || exists $ENV{'FCGI_ROLE'}) { 922*0Sstevel@tonic-gate # can anyone find an easier way to do this? 923*0Sstevel@tonic-gate foreach (keys %{"${namespace}::"}) { 924*0Sstevel@tonic-gate local *symbol = "${namespace}::${_}"; 925*0Sstevel@tonic-gate undef $symbol; 926*0Sstevel@tonic-gate undef @symbol; 927*0Sstevel@tonic-gate undef %symbol; 928*0Sstevel@tonic-gate } 929*0Sstevel@tonic-gate } 930*0Sstevel@tonic-gate my($param,@value,$var); 931*0Sstevel@tonic-gate foreach $param ($self->param) { 932*0Sstevel@tonic-gate # protect against silly names 933*0Sstevel@tonic-gate ($var = $param)=~tr/a-zA-Z0-9_/_/c; 934*0Sstevel@tonic-gate $var =~ s/^(?=\d)/_/; 935*0Sstevel@tonic-gate local *symbol = "${namespace}::$var"; 936*0Sstevel@tonic-gate @value = $self->param($param); 937*0Sstevel@tonic-gate @symbol = @value; 938*0Sstevel@tonic-gate $symbol = $value[0]; 939*0Sstevel@tonic-gate } 940*0Sstevel@tonic-gate} 941*0Sstevel@tonic-gateEND_OF_FUNC 942*0Sstevel@tonic-gate 943*0Sstevel@tonic-gate#### Method: keywords 944*0Sstevel@tonic-gate# Keywords acts a bit differently. Calling it in a list context 945*0Sstevel@tonic-gate# returns the list of keywords. 946*0Sstevel@tonic-gate# Calling it in a scalar context gives you the size of the list. 947*0Sstevel@tonic-gate#### 948*0Sstevel@tonic-gate'keywords' => <<'END_OF_FUNC', 949*0Sstevel@tonic-gatesub keywords { 950*0Sstevel@tonic-gate my($self,@values) = self_or_default(@_); 951*0Sstevel@tonic-gate # If values is provided, then we set it. 952*0Sstevel@tonic-gate $self->{'keywords'}=[@values] if @values; 953*0Sstevel@tonic-gate my(@result) = defined($self->{'keywords'}) ? @{$self->{'keywords'}} : (); 954*0Sstevel@tonic-gate @result; 955*0Sstevel@tonic-gate} 956*0Sstevel@tonic-gateEND_OF_FUNC 957*0Sstevel@tonic-gate 958*0Sstevel@tonic-gate# These are some tie() interfaces for compatibility 959*0Sstevel@tonic-gate# with Steve Brenner's cgi-lib.pl routines 960*0Sstevel@tonic-gate'Vars' => <<'END_OF_FUNC', 961*0Sstevel@tonic-gatesub Vars { 962*0Sstevel@tonic-gate my $q = shift; 963*0Sstevel@tonic-gate my %in; 964*0Sstevel@tonic-gate tie(%in,CGI,$q); 965*0Sstevel@tonic-gate return %in if wantarray; 966*0Sstevel@tonic-gate return \%in; 967*0Sstevel@tonic-gate} 968*0Sstevel@tonic-gateEND_OF_FUNC 969*0Sstevel@tonic-gate 970*0Sstevel@tonic-gate# These are some tie() interfaces for compatibility 971*0Sstevel@tonic-gate# with Steve Brenner's cgi-lib.pl routines 972*0Sstevel@tonic-gate'ReadParse' => <<'END_OF_FUNC', 973*0Sstevel@tonic-gatesub ReadParse { 974*0Sstevel@tonic-gate local(*in); 975*0Sstevel@tonic-gate if (@_) { 976*0Sstevel@tonic-gate *in = $_[0]; 977*0Sstevel@tonic-gate } else { 978*0Sstevel@tonic-gate my $pkg = caller(); 979*0Sstevel@tonic-gate *in=*{"${pkg}::in"}; 980*0Sstevel@tonic-gate } 981*0Sstevel@tonic-gate tie(%in,CGI); 982*0Sstevel@tonic-gate return scalar(keys %in); 983*0Sstevel@tonic-gate} 984*0Sstevel@tonic-gateEND_OF_FUNC 985*0Sstevel@tonic-gate 986*0Sstevel@tonic-gate'PrintHeader' => <<'END_OF_FUNC', 987*0Sstevel@tonic-gatesub PrintHeader { 988*0Sstevel@tonic-gate my($self) = self_or_default(@_); 989*0Sstevel@tonic-gate return $self->header(); 990*0Sstevel@tonic-gate} 991*0Sstevel@tonic-gateEND_OF_FUNC 992*0Sstevel@tonic-gate 993*0Sstevel@tonic-gate'HtmlTop' => <<'END_OF_FUNC', 994*0Sstevel@tonic-gatesub HtmlTop { 995*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 996*0Sstevel@tonic-gate return $self->start_html(@p); 997*0Sstevel@tonic-gate} 998*0Sstevel@tonic-gateEND_OF_FUNC 999*0Sstevel@tonic-gate 1000*0Sstevel@tonic-gate'HtmlBot' => <<'END_OF_FUNC', 1001*0Sstevel@tonic-gatesub HtmlBot { 1002*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 1003*0Sstevel@tonic-gate return $self->end_html(@p); 1004*0Sstevel@tonic-gate} 1005*0Sstevel@tonic-gateEND_OF_FUNC 1006*0Sstevel@tonic-gate 1007*0Sstevel@tonic-gate'SplitParam' => <<'END_OF_FUNC', 1008*0Sstevel@tonic-gatesub SplitParam { 1009*0Sstevel@tonic-gate my ($param) = @_; 1010*0Sstevel@tonic-gate my (@params) = split ("\0", $param); 1011*0Sstevel@tonic-gate return (wantarray ? @params : $params[0]); 1012*0Sstevel@tonic-gate} 1013*0Sstevel@tonic-gateEND_OF_FUNC 1014*0Sstevel@tonic-gate 1015*0Sstevel@tonic-gate'MethGet' => <<'END_OF_FUNC', 1016*0Sstevel@tonic-gatesub MethGet { 1017*0Sstevel@tonic-gate return request_method() eq 'GET'; 1018*0Sstevel@tonic-gate} 1019*0Sstevel@tonic-gateEND_OF_FUNC 1020*0Sstevel@tonic-gate 1021*0Sstevel@tonic-gate'MethPost' => <<'END_OF_FUNC', 1022*0Sstevel@tonic-gatesub MethPost { 1023*0Sstevel@tonic-gate return request_method() eq 'POST'; 1024*0Sstevel@tonic-gate} 1025*0Sstevel@tonic-gateEND_OF_FUNC 1026*0Sstevel@tonic-gate 1027*0Sstevel@tonic-gate'TIEHASH' => <<'END_OF_FUNC', 1028*0Sstevel@tonic-gatesub TIEHASH { 1029*0Sstevel@tonic-gate my $class = shift; 1030*0Sstevel@tonic-gate my $arg = $_[0]; 1031*0Sstevel@tonic-gate if (ref($arg) && UNIVERSAL::isa($arg,'CGI')) { 1032*0Sstevel@tonic-gate return $arg; 1033*0Sstevel@tonic-gate } 1034*0Sstevel@tonic-gate return $Q ||= $class->new(@_); 1035*0Sstevel@tonic-gate} 1036*0Sstevel@tonic-gateEND_OF_FUNC 1037*0Sstevel@tonic-gate 1038*0Sstevel@tonic-gate'STORE' => <<'END_OF_FUNC', 1039*0Sstevel@tonic-gatesub STORE { 1040*0Sstevel@tonic-gate my $self = shift; 1041*0Sstevel@tonic-gate my $tag = shift; 1042*0Sstevel@tonic-gate my $vals = shift; 1043*0Sstevel@tonic-gate my @vals = index($vals,"\0")!=-1 ? split("\0",$vals) : $vals; 1044*0Sstevel@tonic-gate $self->param(-name=>$tag,-value=>\@vals); 1045*0Sstevel@tonic-gate} 1046*0Sstevel@tonic-gateEND_OF_FUNC 1047*0Sstevel@tonic-gate 1048*0Sstevel@tonic-gate'FETCH' => <<'END_OF_FUNC', 1049*0Sstevel@tonic-gatesub FETCH { 1050*0Sstevel@tonic-gate return $_[0] if $_[1] eq 'CGI'; 1051*0Sstevel@tonic-gate return undef unless defined $_[0]->param($_[1]); 1052*0Sstevel@tonic-gate return join("\0",$_[0]->param($_[1])); 1053*0Sstevel@tonic-gate} 1054*0Sstevel@tonic-gateEND_OF_FUNC 1055*0Sstevel@tonic-gate 1056*0Sstevel@tonic-gate'FIRSTKEY' => <<'END_OF_FUNC', 1057*0Sstevel@tonic-gatesub FIRSTKEY { 1058*0Sstevel@tonic-gate $_[0]->{'.iterator'}=0; 1059*0Sstevel@tonic-gate $_[0]->{'.parameters'}->[$_[0]->{'.iterator'}++]; 1060*0Sstevel@tonic-gate} 1061*0Sstevel@tonic-gateEND_OF_FUNC 1062*0Sstevel@tonic-gate 1063*0Sstevel@tonic-gate'NEXTKEY' => <<'END_OF_FUNC', 1064*0Sstevel@tonic-gatesub NEXTKEY { 1065*0Sstevel@tonic-gate $_[0]->{'.parameters'}->[$_[0]->{'.iterator'}++]; 1066*0Sstevel@tonic-gate} 1067*0Sstevel@tonic-gateEND_OF_FUNC 1068*0Sstevel@tonic-gate 1069*0Sstevel@tonic-gate'EXISTS' => <<'END_OF_FUNC', 1070*0Sstevel@tonic-gatesub EXISTS { 1071*0Sstevel@tonic-gate exists $_[0]->{$_[1]}; 1072*0Sstevel@tonic-gate} 1073*0Sstevel@tonic-gateEND_OF_FUNC 1074*0Sstevel@tonic-gate 1075*0Sstevel@tonic-gate'DELETE' => <<'END_OF_FUNC', 1076*0Sstevel@tonic-gatesub DELETE { 1077*0Sstevel@tonic-gate $_[0]->delete($_[1]); 1078*0Sstevel@tonic-gate} 1079*0Sstevel@tonic-gateEND_OF_FUNC 1080*0Sstevel@tonic-gate 1081*0Sstevel@tonic-gate'CLEAR' => <<'END_OF_FUNC', 1082*0Sstevel@tonic-gatesub CLEAR { 1083*0Sstevel@tonic-gate %{$_[0]}=(); 1084*0Sstevel@tonic-gate} 1085*0Sstevel@tonic-gate#### 1086*0Sstevel@tonic-gateEND_OF_FUNC 1087*0Sstevel@tonic-gate 1088*0Sstevel@tonic-gate#### 1089*0Sstevel@tonic-gate# Append a new value to an existing query 1090*0Sstevel@tonic-gate#### 1091*0Sstevel@tonic-gate'append' => <<'EOF', 1092*0Sstevel@tonic-gatesub append { 1093*0Sstevel@tonic-gate my($self,@p) = @_; 1094*0Sstevel@tonic-gate my($name,$value) = rearrange([NAME,[VALUE,VALUES]],@p); 1095*0Sstevel@tonic-gate my(@values) = defined($value) ? (ref($value) ? @{$value} : $value) : (); 1096*0Sstevel@tonic-gate if (@values) { 1097*0Sstevel@tonic-gate $self->add_parameter($name); 1098*0Sstevel@tonic-gate push(@{$self->{$name}},@values); 1099*0Sstevel@tonic-gate } 1100*0Sstevel@tonic-gate return $self->param($name); 1101*0Sstevel@tonic-gate} 1102*0Sstevel@tonic-gateEOF 1103*0Sstevel@tonic-gate 1104*0Sstevel@tonic-gate#### Method: delete_all 1105*0Sstevel@tonic-gate# Delete all parameters 1106*0Sstevel@tonic-gate#### 1107*0Sstevel@tonic-gate'delete_all' => <<'EOF', 1108*0Sstevel@tonic-gatesub delete_all { 1109*0Sstevel@tonic-gate my($self) = self_or_default(@_); 1110*0Sstevel@tonic-gate my @param = $self->param(); 1111*0Sstevel@tonic-gate $self->delete(@param); 1112*0Sstevel@tonic-gate} 1113*0Sstevel@tonic-gateEOF 1114*0Sstevel@tonic-gate 1115*0Sstevel@tonic-gate'Delete' => <<'EOF', 1116*0Sstevel@tonic-gatesub Delete { 1117*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 1118*0Sstevel@tonic-gate $self->delete(@p); 1119*0Sstevel@tonic-gate} 1120*0Sstevel@tonic-gateEOF 1121*0Sstevel@tonic-gate 1122*0Sstevel@tonic-gate'Delete_all' => <<'EOF', 1123*0Sstevel@tonic-gatesub Delete_all { 1124*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 1125*0Sstevel@tonic-gate $self->delete_all(@p); 1126*0Sstevel@tonic-gate} 1127*0Sstevel@tonic-gateEOF 1128*0Sstevel@tonic-gate 1129*0Sstevel@tonic-gate#### Method: autoescape 1130*0Sstevel@tonic-gate# If you want to turn off the autoescaping features, 1131*0Sstevel@tonic-gate# call this method with undef as the argument 1132*0Sstevel@tonic-gate'autoEscape' => <<'END_OF_FUNC', 1133*0Sstevel@tonic-gatesub autoEscape { 1134*0Sstevel@tonic-gate my($self,$escape) = self_or_default(@_); 1135*0Sstevel@tonic-gate my $d = $self->{'escape'}; 1136*0Sstevel@tonic-gate $self->{'escape'} = $escape; 1137*0Sstevel@tonic-gate $d; 1138*0Sstevel@tonic-gate} 1139*0Sstevel@tonic-gateEND_OF_FUNC 1140*0Sstevel@tonic-gate 1141*0Sstevel@tonic-gate 1142*0Sstevel@tonic-gate#### Method: version 1143*0Sstevel@tonic-gate# Return the current version 1144*0Sstevel@tonic-gate#### 1145*0Sstevel@tonic-gate'version' => <<'END_OF_FUNC', 1146*0Sstevel@tonic-gatesub version { 1147*0Sstevel@tonic-gate return $VERSION; 1148*0Sstevel@tonic-gate} 1149*0Sstevel@tonic-gateEND_OF_FUNC 1150*0Sstevel@tonic-gate 1151*0Sstevel@tonic-gate#### Method: url_param 1152*0Sstevel@tonic-gate# Return a parameter in the QUERY_STRING, regardless of 1153*0Sstevel@tonic-gate# whether this was a POST or a GET 1154*0Sstevel@tonic-gate#### 1155*0Sstevel@tonic-gate'url_param' => <<'END_OF_FUNC', 1156*0Sstevel@tonic-gatesub url_param { 1157*0Sstevel@tonic-gate my ($self,@p) = self_or_default(@_); 1158*0Sstevel@tonic-gate my $name = shift(@p); 1159*0Sstevel@tonic-gate return undef unless exists($ENV{QUERY_STRING}); 1160*0Sstevel@tonic-gate unless (exists($self->{'.url_param'})) { 1161*0Sstevel@tonic-gate $self->{'.url_param'}={}; # empty hash 1162*0Sstevel@tonic-gate if ($ENV{QUERY_STRING} =~ /=/) { 1163*0Sstevel@tonic-gate my(@pairs) = split(/[&;]/,$ENV{QUERY_STRING}); 1164*0Sstevel@tonic-gate my($param,$value); 1165*0Sstevel@tonic-gate foreach (@pairs) { 1166*0Sstevel@tonic-gate ($param,$value) = split('=',$_,2); 1167*0Sstevel@tonic-gate $param = unescape($param); 1168*0Sstevel@tonic-gate $value = unescape($value); 1169*0Sstevel@tonic-gate push(@{$self->{'.url_param'}->{$param}},$value); 1170*0Sstevel@tonic-gate } 1171*0Sstevel@tonic-gate } else { 1172*0Sstevel@tonic-gate $self->{'.url_param'}->{'keywords'} = [$self->parse_keywordlist($ENV{QUERY_STRING})]; 1173*0Sstevel@tonic-gate } 1174*0Sstevel@tonic-gate } 1175*0Sstevel@tonic-gate return keys %{$self->{'.url_param'}} unless defined($name); 1176*0Sstevel@tonic-gate return () unless $self->{'.url_param'}->{$name}; 1177*0Sstevel@tonic-gate return wantarray ? @{$self->{'.url_param'}->{$name}} 1178*0Sstevel@tonic-gate : $self->{'.url_param'}->{$name}->[0]; 1179*0Sstevel@tonic-gate} 1180*0Sstevel@tonic-gateEND_OF_FUNC 1181*0Sstevel@tonic-gate 1182*0Sstevel@tonic-gate#### Method: Dump 1183*0Sstevel@tonic-gate# Returns a string in which all the known parameter/value 1184*0Sstevel@tonic-gate# pairs are represented as nested lists, mainly for the purposes 1185*0Sstevel@tonic-gate# of debugging. 1186*0Sstevel@tonic-gate#### 1187*0Sstevel@tonic-gate'Dump' => <<'END_OF_FUNC', 1188*0Sstevel@tonic-gatesub Dump { 1189*0Sstevel@tonic-gate my($self) = self_or_default(@_); 1190*0Sstevel@tonic-gate my($param,$value,@result); 1191*0Sstevel@tonic-gate return '<ul></ul>' unless $self->param; 1192*0Sstevel@tonic-gate push(@result,"<ul>"); 1193*0Sstevel@tonic-gate foreach $param ($self->param) { 1194*0Sstevel@tonic-gate my($name)=$self->escapeHTML($param); 1195*0Sstevel@tonic-gate push(@result,"<li><strong>$param</strong></li>"); 1196*0Sstevel@tonic-gate push(@result,"<ul>"); 1197*0Sstevel@tonic-gate foreach $value ($self->param($param)) { 1198*0Sstevel@tonic-gate $value = $self->escapeHTML($value); 1199*0Sstevel@tonic-gate $value =~ s/\n/<br \/>\n/g; 1200*0Sstevel@tonic-gate push(@result,"<li>$value</li>"); 1201*0Sstevel@tonic-gate } 1202*0Sstevel@tonic-gate push(@result,"</ul>"); 1203*0Sstevel@tonic-gate } 1204*0Sstevel@tonic-gate push(@result,"</ul>"); 1205*0Sstevel@tonic-gate return join("\n",@result); 1206*0Sstevel@tonic-gate} 1207*0Sstevel@tonic-gateEND_OF_FUNC 1208*0Sstevel@tonic-gate 1209*0Sstevel@tonic-gate#### Method as_string 1210*0Sstevel@tonic-gate# 1211*0Sstevel@tonic-gate# synonym for "dump" 1212*0Sstevel@tonic-gate#### 1213*0Sstevel@tonic-gate'as_string' => <<'END_OF_FUNC', 1214*0Sstevel@tonic-gatesub as_string { 1215*0Sstevel@tonic-gate &Dump(@_); 1216*0Sstevel@tonic-gate} 1217*0Sstevel@tonic-gateEND_OF_FUNC 1218*0Sstevel@tonic-gate 1219*0Sstevel@tonic-gate#### Method: save 1220*0Sstevel@tonic-gate# Write values out to a filehandle in such a way that they can 1221*0Sstevel@tonic-gate# be reinitialized by the filehandle form of the new() method 1222*0Sstevel@tonic-gate#### 1223*0Sstevel@tonic-gate'save' => <<'END_OF_FUNC', 1224*0Sstevel@tonic-gatesub save { 1225*0Sstevel@tonic-gate my($self,$filehandle) = self_or_default(@_); 1226*0Sstevel@tonic-gate $filehandle = to_filehandle($filehandle); 1227*0Sstevel@tonic-gate my($param); 1228*0Sstevel@tonic-gate local($,) = ''; # set print field separator back to a sane value 1229*0Sstevel@tonic-gate local($\) = ''; # set output line separator to a sane value 1230*0Sstevel@tonic-gate foreach $param ($self->param) { 1231*0Sstevel@tonic-gate my($escaped_param) = escape($param); 1232*0Sstevel@tonic-gate my($value); 1233*0Sstevel@tonic-gate foreach $value ($self->param($param)) { 1234*0Sstevel@tonic-gate print $filehandle "$escaped_param=",escape("$value"),"\n"; 1235*0Sstevel@tonic-gate } 1236*0Sstevel@tonic-gate } 1237*0Sstevel@tonic-gate foreach (keys %{$self->{'.fieldnames'}}) { 1238*0Sstevel@tonic-gate print $filehandle ".cgifields=",escape("$_"),"\n"; 1239*0Sstevel@tonic-gate } 1240*0Sstevel@tonic-gate print $filehandle "=\n"; # end of record 1241*0Sstevel@tonic-gate} 1242*0Sstevel@tonic-gateEND_OF_FUNC 1243*0Sstevel@tonic-gate 1244*0Sstevel@tonic-gate 1245*0Sstevel@tonic-gate#### Method: save_parameters 1246*0Sstevel@tonic-gate# An alias for save() that is a better name for exportation. 1247*0Sstevel@tonic-gate# Only intended to be used with the function (non-OO) interface. 1248*0Sstevel@tonic-gate#### 1249*0Sstevel@tonic-gate'save_parameters' => <<'END_OF_FUNC', 1250*0Sstevel@tonic-gatesub save_parameters { 1251*0Sstevel@tonic-gate my $fh = shift; 1252*0Sstevel@tonic-gate return save(to_filehandle($fh)); 1253*0Sstevel@tonic-gate} 1254*0Sstevel@tonic-gateEND_OF_FUNC 1255*0Sstevel@tonic-gate 1256*0Sstevel@tonic-gate#### Method: restore_parameters 1257*0Sstevel@tonic-gate# A way to restore CGI parameters from an initializer. 1258*0Sstevel@tonic-gate# Only intended to be used with the function (non-OO) interface. 1259*0Sstevel@tonic-gate#### 1260*0Sstevel@tonic-gate'restore_parameters' => <<'END_OF_FUNC', 1261*0Sstevel@tonic-gatesub restore_parameters { 1262*0Sstevel@tonic-gate $Q = $CGI::DefaultClass->new(@_); 1263*0Sstevel@tonic-gate} 1264*0Sstevel@tonic-gateEND_OF_FUNC 1265*0Sstevel@tonic-gate 1266*0Sstevel@tonic-gate#### Method: multipart_init 1267*0Sstevel@tonic-gate# Return a Content-Type: style header for server-push 1268*0Sstevel@tonic-gate# This has to be NPH on most web servers, and it is advisable to set $| = 1 1269*0Sstevel@tonic-gate# 1270*0Sstevel@tonic-gate# Many thanks to Ed Jordan <ed@fidalgo.net> for this 1271*0Sstevel@tonic-gate# contribution, updated by Andrew Benham (adsb@bigfoot.com) 1272*0Sstevel@tonic-gate#### 1273*0Sstevel@tonic-gate'multipart_init' => <<'END_OF_FUNC', 1274*0Sstevel@tonic-gatesub multipart_init { 1275*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 1276*0Sstevel@tonic-gate my($boundary,@other) = rearrange([BOUNDARY],@p); 1277*0Sstevel@tonic-gate $boundary = $boundary || '------- =_aaaaaaaaaa0'; 1278*0Sstevel@tonic-gate $self->{'separator'} = "$CRLF--$boundary$CRLF"; 1279*0Sstevel@tonic-gate $self->{'final_separator'} = "$CRLF--$boundary--$CRLF"; 1280*0Sstevel@tonic-gate $type = SERVER_PUSH($boundary); 1281*0Sstevel@tonic-gate return $self->header( 1282*0Sstevel@tonic-gate -nph => 1, 1283*0Sstevel@tonic-gate -type => $type, 1284*0Sstevel@tonic-gate (map { split "=", $_, 2 } @other), 1285*0Sstevel@tonic-gate ) . "WARNING: YOUR BROWSER DOESN'T SUPPORT THIS SERVER-PUSH TECHNOLOGY." . $self->multipart_end; 1286*0Sstevel@tonic-gate} 1287*0Sstevel@tonic-gateEND_OF_FUNC 1288*0Sstevel@tonic-gate 1289*0Sstevel@tonic-gate 1290*0Sstevel@tonic-gate#### Method: multipart_start 1291*0Sstevel@tonic-gate# Return a Content-Type: style header for server-push, start of section 1292*0Sstevel@tonic-gate# 1293*0Sstevel@tonic-gate# Many thanks to Ed Jordan <ed@fidalgo.net> for this 1294*0Sstevel@tonic-gate# contribution, updated by Andrew Benham (adsb@bigfoot.com) 1295*0Sstevel@tonic-gate#### 1296*0Sstevel@tonic-gate'multipart_start' => <<'END_OF_FUNC', 1297*0Sstevel@tonic-gatesub multipart_start { 1298*0Sstevel@tonic-gate my(@header); 1299*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 1300*0Sstevel@tonic-gate my($type,@other) = rearrange([TYPE],@p); 1301*0Sstevel@tonic-gate $type = $type || 'text/html'; 1302*0Sstevel@tonic-gate push(@header,"Content-Type: $type"); 1303*0Sstevel@tonic-gate 1304*0Sstevel@tonic-gate # rearrange() was designed for the HTML portion, so we 1305*0Sstevel@tonic-gate # need to fix it up a little. 1306*0Sstevel@tonic-gate foreach (@other) { 1307*0Sstevel@tonic-gate # Don't use \s because of perl bug 21951 1308*0Sstevel@tonic-gate next unless my($header,$value) = /([^ \r\n\t=]+)=\"?(.+?)\"?$/; 1309*0Sstevel@tonic-gate ($_ = $header) =~ s/^(\w)(.*)/$1 . lc ($2) . ': '.$self->unescapeHTML($value)/e; 1310*0Sstevel@tonic-gate } 1311*0Sstevel@tonic-gate push(@header,@other); 1312*0Sstevel@tonic-gate my $header = join($CRLF,@header)."${CRLF}${CRLF}"; 1313*0Sstevel@tonic-gate return $header; 1314*0Sstevel@tonic-gate} 1315*0Sstevel@tonic-gateEND_OF_FUNC 1316*0Sstevel@tonic-gate 1317*0Sstevel@tonic-gate 1318*0Sstevel@tonic-gate#### Method: multipart_end 1319*0Sstevel@tonic-gate# Return a MIME boundary separator for server-push, end of section 1320*0Sstevel@tonic-gate# 1321*0Sstevel@tonic-gate# Many thanks to Ed Jordan <ed@fidalgo.net> for this 1322*0Sstevel@tonic-gate# contribution 1323*0Sstevel@tonic-gate#### 1324*0Sstevel@tonic-gate'multipart_end' => <<'END_OF_FUNC', 1325*0Sstevel@tonic-gatesub multipart_end { 1326*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 1327*0Sstevel@tonic-gate return $self->{'separator'}; 1328*0Sstevel@tonic-gate} 1329*0Sstevel@tonic-gateEND_OF_FUNC 1330*0Sstevel@tonic-gate 1331*0Sstevel@tonic-gate 1332*0Sstevel@tonic-gate#### Method: multipart_final 1333*0Sstevel@tonic-gate# Return a MIME boundary separator for server-push, end of all sections 1334*0Sstevel@tonic-gate# 1335*0Sstevel@tonic-gate# Contributed by Andrew Benham (adsb@bigfoot.com) 1336*0Sstevel@tonic-gate#### 1337*0Sstevel@tonic-gate'multipart_final' => <<'END_OF_FUNC', 1338*0Sstevel@tonic-gatesub multipart_final { 1339*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 1340*0Sstevel@tonic-gate return $self->{'final_separator'} . "WARNING: YOUR BROWSER DOESN'T SUPPORT THIS SERVER-PUSH TECHNOLOGY." . $CRLF; 1341*0Sstevel@tonic-gate} 1342*0Sstevel@tonic-gateEND_OF_FUNC 1343*0Sstevel@tonic-gate 1344*0Sstevel@tonic-gate 1345*0Sstevel@tonic-gate#### Method: header 1346*0Sstevel@tonic-gate# Return a Content-Type: style header 1347*0Sstevel@tonic-gate# 1348*0Sstevel@tonic-gate#### 1349*0Sstevel@tonic-gate'header' => <<'END_OF_FUNC', 1350*0Sstevel@tonic-gatesub header { 1351*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 1352*0Sstevel@tonic-gate my(@header); 1353*0Sstevel@tonic-gate 1354*0Sstevel@tonic-gate return "" if $self->{'.header_printed'}++ and $HEADERS_ONCE; 1355*0Sstevel@tonic-gate 1356*0Sstevel@tonic-gate my($type,$status,$cookie,$target,$expires,$nph,$charset,$attachment,$p3p,@other) = 1357*0Sstevel@tonic-gate rearrange([['TYPE','CONTENT_TYPE','CONTENT-TYPE'], 1358*0Sstevel@tonic-gate 'STATUS',['COOKIE','COOKIES'],'TARGET', 1359*0Sstevel@tonic-gate 'EXPIRES','NPH','CHARSET', 1360*0Sstevel@tonic-gate 'ATTACHMENT','P3P'],@p); 1361*0Sstevel@tonic-gate 1362*0Sstevel@tonic-gate $nph ||= $NPH; 1363*0Sstevel@tonic-gate if (defined $charset) { 1364*0Sstevel@tonic-gate $self->charset($charset); 1365*0Sstevel@tonic-gate } else { 1366*0Sstevel@tonic-gate $charset = $self->charset; 1367*0Sstevel@tonic-gate } 1368*0Sstevel@tonic-gate 1369*0Sstevel@tonic-gate # rearrange() was designed for the HTML portion, so we 1370*0Sstevel@tonic-gate # need to fix it up a little. 1371*0Sstevel@tonic-gate foreach (@other) { 1372*0Sstevel@tonic-gate # Don't use \s because of perl bug 21951 1373*0Sstevel@tonic-gate next unless my($header,$value) = /([^ \r\n\t=]+)=\"?(.+?)\"?$/; 1374*0Sstevel@tonic-gate ($_ = $header) =~ s/^(\w)(.*)/"\u$1\L$2" . ': '.$self->unescapeHTML($value)/e; 1375*0Sstevel@tonic-gate } 1376*0Sstevel@tonic-gate 1377*0Sstevel@tonic-gate $type ||= 'text/html' unless defined($type); 1378*0Sstevel@tonic-gate $type .= "; charset=$charset" if $type ne '' and $type =~ m!^text/! and $type !~ /\bcharset\b/ and $charset ne ''; 1379*0Sstevel@tonic-gate 1380*0Sstevel@tonic-gate # Maybe future compatibility. Maybe not. 1381*0Sstevel@tonic-gate my $protocol = $ENV{SERVER_PROTOCOL} || 'HTTP/1.0'; 1382*0Sstevel@tonic-gate push(@header,$protocol . ' ' . ($status || '200 OK')) if $nph; 1383*0Sstevel@tonic-gate push(@header,"Server: " . &server_software()) if $nph; 1384*0Sstevel@tonic-gate 1385*0Sstevel@tonic-gate push(@header,"Status: $status") if $status; 1386*0Sstevel@tonic-gate push(@header,"Window-Target: $target") if $target; 1387*0Sstevel@tonic-gate if ($p3p) { 1388*0Sstevel@tonic-gate $p3p = join ' ',@$p3p if ref($p3p) eq 'ARRAY'; 1389*0Sstevel@tonic-gate push(@header,qq(P3P: policyref="/w3c/p3p.xml", CP="$p3p")); 1390*0Sstevel@tonic-gate } 1391*0Sstevel@tonic-gate # push all the cookies -- there may be several 1392*0Sstevel@tonic-gate if ($cookie) { 1393*0Sstevel@tonic-gate my(@cookie) = ref($cookie) && ref($cookie) eq 'ARRAY' ? @{$cookie} : $cookie; 1394*0Sstevel@tonic-gate foreach (@cookie) { 1395*0Sstevel@tonic-gate my $cs = UNIVERSAL::isa($_,'CGI::Cookie') ? $_->as_string : $_; 1396*0Sstevel@tonic-gate push(@header,"Set-Cookie: $cs") if $cs ne ''; 1397*0Sstevel@tonic-gate } 1398*0Sstevel@tonic-gate } 1399*0Sstevel@tonic-gate # if the user indicates an expiration time, then we need 1400*0Sstevel@tonic-gate # both an Expires and a Date header (so that the browser is 1401*0Sstevel@tonic-gate # uses OUR clock) 1402*0Sstevel@tonic-gate push(@header,"Expires: " . expires($expires,'http')) 1403*0Sstevel@tonic-gate if $expires; 1404*0Sstevel@tonic-gate push(@header,"Date: " . expires(0,'http')) if $expires || $cookie || $nph; 1405*0Sstevel@tonic-gate push(@header,"Pragma: no-cache") if $self->cache(); 1406*0Sstevel@tonic-gate push(@header,"Content-Disposition: attachment; filename=\"$attachment\"") if $attachment; 1407*0Sstevel@tonic-gate push(@header,map {ucfirst $_} @other); 1408*0Sstevel@tonic-gate push(@header,"Content-Type: $type") if $type ne ''; 1409*0Sstevel@tonic-gate my $header = join($CRLF,@header)."${CRLF}${CRLF}"; 1410*0Sstevel@tonic-gate if ($MOD_PERL and not $nph) { 1411*0Sstevel@tonic-gate $self->r->send_cgi_header($header); 1412*0Sstevel@tonic-gate return ''; 1413*0Sstevel@tonic-gate } 1414*0Sstevel@tonic-gate return $header; 1415*0Sstevel@tonic-gate} 1416*0Sstevel@tonic-gateEND_OF_FUNC 1417*0Sstevel@tonic-gate 1418*0Sstevel@tonic-gate 1419*0Sstevel@tonic-gate#### Method: cache 1420*0Sstevel@tonic-gate# Control whether header() will produce the no-cache 1421*0Sstevel@tonic-gate# Pragma directive. 1422*0Sstevel@tonic-gate#### 1423*0Sstevel@tonic-gate'cache' => <<'END_OF_FUNC', 1424*0Sstevel@tonic-gatesub cache { 1425*0Sstevel@tonic-gate my($self,$new_value) = self_or_default(@_); 1426*0Sstevel@tonic-gate $new_value = '' unless $new_value; 1427*0Sstevel@tonic-gate if ($new_value ne '') { 1428*0Sstevel@tonic-gate $self->{'cache'} = $new_value; 1429*0Sstevel@tonic-gate } 1430*0Sstevel@tonic-gate return $self->{'cache'}; 1431*0Sstevel@tonic-gate} 1432*0Sstevel@tonic-gateEND_OF_FUNC 1433*0Sstevel@tonic-gate 1434*0Sstevel@tonic-gate 1435*0Sstevel@tonic-gate#### Method: redirect 1436*0Sstevel@tonic-gate# Return a Location: style header 1437*0Sstevel@tonic-gate# 1438*0Sstevel@tonic-gate#### 1439*0Sstevel@tonic-gate'redirect' => <<'END_OF_FUNC', 1440*0Sstevel@tonic-gatesub redirect { 1441*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 1442*0Sstevel@tonic-gate my($url,$target,$cookie,$nph,@other) = rearrange([[LOCATION,URI,URL],TARGET,['COOKIE','COOKIES'],NPH],@p); 1443*0Sstevel@tonic-gate $url ||= $self->self_url; 1444*0Sstevel@tonic-gate my(@o); 1445*0Sstevel@tonic-gate foreach (@other) { tr/\"//d; push(@o,split("=",$_,2)); } 1446*0Sstevel@tonic-gate unshift(@o, 1447*0Sstevel@tonic-gate '-Status' => '302 Moved', 1448*0Sstevel@tonic-gate '-Location'=> $url, 1449*0Sstevel@tonic-gate '-nph' => $nph); 1450*0Sstevel@tonic-gate unshift(@o,'-Target'=>$target) if $target; 1451*0Sstevel@tonic-gate unshift(@o,'-Type'=>''); 1452*0Sstevel@tonic-gate my @unescaped; 1453*0Sstevel@tonic-gate unshift(@unescaped,'-Cookie'=>$cookie) if $cookie; 1454*0Sstevel@tonic-gate return $self->header((map {$self->unescapeHTML($_)} @o),@unescaped); 1455*0Sstevel@tonic-gate} 1456*0Sstevel@tonic-gateEND_OF_FUNC 1457*0Sstevel@tonic-gate 1458*0Sstevel@tonic-gate 1459*0Sstevel@tonic-gate#### Method: start_html 1460*0Sstevel@tonic-gate# Canned HTML header 1461*0Sstevel@tonic-gate# 1462*0Sstevel@tonic-gate# Parameters: 1463*0Sstevel@tonic-gate# $title -> (optional) The title for this HTML document (-title) 1464*0Sstevel@tonic-gate# $author -> (optional) e-mail address of the author (-author) 1465*0Sstevel@tonic-gate# $base -> (optional) if set to true, will enter the BASE address of this document 1466*0Sstevel@tonic-gate# for resolving relative references (-base) 1467*0Sstevel@tonic-gate# $xbase -> (optional) alternative base at some remote location (-xbase) 1468*0Sstevel@tonic-gate# $target -> (optional) target window to load all links into (-target) 1469*0Sstevel@tonic-gate# $script -> (option) Javascript code (-script) 1470*0Sstevel@tonic-gate# $no_script -> (option) Javascript <noscript> tag (-noscript) 1471*0Sstevel@tonic-gate# $meta -> (optional) Meta information tags 1472*0Sstevel@tonic-gate# $head -> (optional) any other elements you'd like to incorporate into the <head> tag 1473*0Sstevel@tonic-gate# (a scalar or array ref) 1474*0Sstevel@tonic-gate# $style -> (optional) reference to an external style sheet 1475*0Sstevel@tonic-gate# @other -> (optional) any other named parameters you'd like to incorporate into 1476*0Sstevel@tonic-gate# the <body> tag. 1477*0Sstevel@tonic-gate#### 1478*0Sstevel@tonic-gate'start_html' => <<'END_OF_FUNC', 1479*0Sstevel@tonic-gatesub start_html { 1480*0Sstevel@tonic-gate my($self,@p) = &self_or_default(@_); 1481*0Sstevel@tonic-gate my($title,$author,$base,$xbase,$script,$noscript, 1482*0Sstevel@tonic-gate $target,$meta,$head,$style,$dtd,$lang,$encoding,@other) = 1483*0Sstevel@tonic-gate rearrange([TITLE,AUTHOR,BASE,XBASE,SCRIPT,NOSCRIPT,TARGET,META,HEAD,STYLE,DTD,LANG,ENCODING],@p); 1484*0Sstevel@tonic-gate 1485*0Sstevel@tonic-gate $encoding = 'iso-8859-1' unless defined $encoding; 1486*0Sstevel@tonic-gate 1487*0Sstevel@tonic-gate # strangely enough, the title needs to be escaped as HTML 1488*0Sstevel@tonic-gate # while the author needs to be escaped as a URL 1489*0Sstevel@tonic-gate $title = $self->escapeHTML($title || 'Untitled Document'); 1490*0Sstevel@tonic-gate $author = $self->escape($author); 1491*0Sstevel@tonic-gate $lang = 'en-US' unless defined $lang; 1492*0Sstevel@tonic-gate my(@result,$xml_dtd); 1493*0Sstevel@tonic-gate if ($dtd) { 1494*0Sstevel@tonic-gate if (defined(ref($dtd)) and (ref($dtd) eq 'ARRAY')) { 1495*0Sstevel@tonic-gate $dtd = $DEFAULT_DTD unless $dtd->[0] =~ m|^-//|; 1496*0Sstevel@tonic-gate } else { 1497*0Sstevel@tonic-gate $dtd = $DEFAULT_DTD unless $dtd =~ m|^-//|; 1498*0Sstevel@tonic-gate } 1499*0Sstevel@tonic-gate } else { 1500*0Sstevel@tonic-gate $dtd = $XHTML ? XHTML_DTD : $DEFAULT_DTD; 1501*0Sstevel@tonic-gate } 1502*0Sstevel@tonic-gate 1503*0Sstevel@tonic-gate $xml_dtd++ if ref($dtd) eq 'ARRAY' && $dtd->[0] =~ /\bXHTML\b/i; 1504*0Sstevel@tonic-gate $xml_dtd++ if ref($dtd) eq '' && $dtd =~ /\bXHTML\b/i; 1505*0Sstevel@tonic-gate push @result,qq(<?xml version="1.0" encoding="$encoding"?>) if $xml_dtd; 1506*0Sstevel@tonic-gate 1507*0Sstevel@tonic-gate if (ref($dtd) && ref($dtd) eq 'ARRAY') { 1508*0Sstevel@tonic-gate push(@result,qq(<!DOCTYPE html\n\tPUBLIC "$dtd->[0]"\n\t "$dtd->[1]">)); 1509*0Sstevel@tonic-gate } else { 1510*0Sstevel@tonic-gate push(@result,qq(<!DOCTYPE html\n\tPUBLIC "$dtd">)); 1511*0Sstevel@tonic-gate } 1512*0Sstevel@tonic-gate push(@result,$XHTML ? qq(<html xmlns="http://www.w3.org/1999/xhtml" lang="$lang" xml:lang="$lang"><head><title>$title</title>) 1513*0Sstevel@tonic-gate : ($lang ? qq(<html lang="$lang">) : "<html>") 1514*0Sstevel@tonic-gate . "<head><title>$title</title>"); 1515*0Sstevel@tonic-gate if (defined $author) { 1516*0Sstevel@tonic-gate push(@result,$XHTML ? "<link rev=\"made\" href=\"mailto:$author\" />" 1517*0Sstevel@tonic-gate : "<link rev=\"made\" href=\"mailto:$author\">"); 1518*0Sstevel@tonic-gate } 1519*0Sstevel@tonic-gate 1520*0Sstevel@tonic-gate if ($base || $xbase || $target) { 1521*0Sstevel@tonic-gate my $href = $xbase || $self->url('-path'=>1); 1522*0Sstevel@tonic-gate my $t = $target ? qq/ target="$target"/ : ''; 1523*0Sstevel@tonic-gate push(@result,$XHTML ? qq(<base href="$href"$t />) : qq(<base href="$href"$t>)); 1524*0Sstevel@tonic-gate } 1525*0Sstevel@tonic-gate 1526*0Sstevel@tonic-gate if ($meta && ref($meta) && (ref($meta) eq 'HASH')) { 1527*0Sstevel@tonic-gate foreach (keys %$meta) { push(@result,$XHTML ? qq(<meta name="$_" content="$meta->{$_}" />) 1528*0Sstevel@tonic-gate : qq(<meta name="$_" content="$meta->{$_}">)); } 1529*0Sstevel@tonic-gate } 1530*0Sstevel@tonic-gate 1531*0Sstevel@tonic-gate push(@result,ref($head) ? @$head : $head) if $head; 1532*0Sstevel@tonic-gate 1533*0Sstevel@tonic-gate # handle the infrequently-used -style and -script parameters 1534*0Sstevel@tonic-gate push(@result,$self->_style($style)) if defined $style; 1535*0Sstevel@tonic-gate push(@result,$self->_script($script)) if defined $script; 1536*0Sstevel@tonic-gate 1537*0Sstevel@tonic-gate # handle -noscript parameter 1538*0Sstevel@tonic-gate push(@result,<<END) if $noscript; 1539*0Sstevel@tonic-gate<noscript> 1540*0Sstevel@tonic-gate$noscript 1541*0Sstevel@tonic-gate</noscript> 1542*0Sstevel@tonic-gateEND 1543*0Sstevel@tonic-gate ; 1544*0Sstevel@tonic-gate my($other) = @other ? " @other" : ''; 1545*0Sstevel@tonic-gate push(@result,"</head><body$other>"); 1546*0Sstevel@tonic-gate return join("\n",@result); 1547*0Sstevel@tonic-gate} 1548*0Sstevel@tonic-gateEND_OF_FUNC 1549*0Sstevel@tonic-gate 1550*0Sstevel@tonic-gate### Method: _style 1551*0Sstevel@tonic-gate# internal method for generating a CSS style section 1552*0Sstevel@tonic-gate#### 1553*0Sstevel@tonic-gate'_style' => <<'END_OF_FUNC', 1554*0Sstevel@tonic-gatesub _style { 1555*0Sstevel@tonic-gate my ($self,$style) = @_; 1556*0Sstevel@tonic-gate my (@result); 1557*0Sstevel@tonic-gate my $type = 'text/css'; 1558*0Sstevel@tonic-gate 1559*0Sstevel@tonic-gate my $cdata_start = $XHTML ? "\n<!--/* <![CDATA[ */" : "\n<!-- "; 1560*0Sstevel@tonic-gate my $cdata_end = $XHTML ? "\n/* ]]> */-->\n" : " -->\n"; 1561*0Sstevel@tonic-gate 1562*0Sstevel@tonic-gate if (ref($style)) { 1563*0Sstevel@tonic-gate my($src,$code,$verbatim,$stype,$foo,@other) = 1564*0Sstevel@tonic-gate rearrange([SRC,CODE,VERBATIM,TYPE], 1565*0Sstevel@tonic-gate '-foo'=>'bar', # trick to allow dash to be omitted 1566*0Sstevel@tonic-gate ref($style) eq 'ARRAY' ? @$style : %$style); 1567*0Sstevel@tonic-gate $type = $stype if $stype; 1568*0Sstevel@tonic-gate my $other = @other ? join ' ',@other : ''; 1569*0Sstevel@tonic-gate 1570*0Sstevel@tonic-gate if (ref($src) eq "ARRAY") # Check to see if the $src variable is an array reference 1571*0Sstevel@tonic-gate { # If it is, push a LINK tag for each one 1572*0Sstevel@tonic-gate foreach $src (@$src) 1573*0Sstevel@tonic-gate { 1574*0Sstevel@tonic-gate push(@result,$XHTML ? qq(<link rel="stylesheet" type="$type" href="$src" $other/>) 1575*0Sstevel@tonic-gate : qq(<link rel="stylesheet" type="$type" href="$src"$other>)) if $src; 1576*0Sstevel@tonic-gate } 1577*0Sstevel@tonic-gate } 1578*0Sstevel@tonic-gate else 1579*0Sstevel@tonic-gate { # Otherwise, push the single -src, if it exists. 1580*0Sstevel@tonic-gate push(@result,$XHTML ? qq(<link rel="stylesheet" type="$type" href="$src" $other/>) 1581*0Sstevel@tonic-gate : qq(<link rel="stylesheet" type="$type" href="$src"$other>) 1582*0Sstevel@tonic-gate ) if $src; 1583*0Sstevel@tonic-gate } 1584*0Sstevel@tonic-gate if ($verbatim) { 1585*0Sstevel@tonic-gate push(@result, "<style type=\"text/css\">\n$verbatim\n</style>"); 1586*0Sstevel@tonic-gate } 1587*0Sstevel@tonic-gate push(@result,style({'type'=>$type},"$cdata_start\n$code\n$cdata_end")) if $code; 1588*0Sstevel@tonic-gate } else { 1589*0Sstevel@tonic-gate my $src = $style; 1590*0Sstevel@tonic-gate push(@result,$XHTML ? qq(<link rel="stylesheet" type="$type" href="$src" $other/>) 1591*0Sstevel@tonic-gate : qq(<link rel="stylesheet" type="$type" href="$src"$other>)); 1592*0Sstevel@tonic-gate } 1593*0Sstevel@tonic-gate @result; 1594*0Sstevel@tonic-gate} 1595*0Sstevel@tonic-gateEND_OF_FUNC 1596*0Sstevel@tonic-gate 1597*0Sstevel@tonic-gate'_script' => <<'END_OF_FUNC', 1598*0Sstevel@tonic-gatesub _script { 1599*0Sstevel@tonic-gate my ($self,$script) = @_; 1600*0Sstevel@tonic-gate my (@result); 1601*0Sstevel@tonic-gate 1602*0Sstevel@tonic-gate my (@scripts) = ref($script) eq 'ARRAY' ? @$script : ($script); 1603*0Sstevel@tonic-gate foreach $script (@scripts) { 1604*0Sstevel@tonic-gate my($src,$code,$language); 1605*0Sstevel@tonic-gate if (ref($script)) { # script is a hash 1606*0Sstevel@tonic-gate ($src,$code,$language, $type) = 1607*0Sstevel@tonic-gate rearrange([SRC,CODE,LANGUAGE,TYPE], 1608*0Sstevel@tonic-gate '-foo'=>'bar', # a trick to allow the '-' to be omitted 1609*0Sstevel@tonic-gate ref($script) eq 'ARRAY' ? @$script : %$script); 1610*0Sstevel@tonic-gate # User may not have specified language 1611*0Sstevel@tonic-gate $language ||= 'JavaScript'; 1612*0Sstevel@tonic-gate unless (defined $type) { 1613*0Sstevel@tonic-gate $type = lc $language; 1614*0Sstevel@tonic-gate # strip '1.2' from 'javascript1.2' 1615*0Sstevel@tonic-gate $type =~ s/^(\D+).*$/text\/$1/; 1616*0Sstevel@tonic-gate } 1617*0Sstevel@tonic-gate } else { 1618*0Sstevel@tonic-gate ($src,$code,$language, $type) = ('',$script,'JavaScript', 'text/javascript'); 1619*0Sstevel@tonic-gate } 1620*0Sstevel@tonic-gate 1621*0Sstevel@tonic-gate my $comment = '//'; # javascript by default 1622*0Sstevel@tonic-gate $comment = '#' if $type=~/perl|tcl/i; 1623*0Sstevel@tonic-gate $comment = "'" if $type=~/vbscript/i; 1624*0Sstevel@tonic-gate 1625*0Sstevel@tonic-gate my ($cdata_start,$cdata_end); 1626*0Sstevel@tonic-gate if ($XHTML) { 1627*0Sstevel@tonic-gate $cdata_start = "$comment<![CDATA[\n"; 1628*0Sstevel@tonic-gate $cdata_end .= "\n$comment]]>"; 1629*0Sstevel@tonic-gate } else { 1630*0Sstevel@tonic-gate $cdata_start = "\n<!-- Hide script\n"; 1631*0Sstevel@tonic-gate $cdata_end = $comment; 1632*0Sstevel@tonic-gate $cdata_end .= " End script hiding -->\n"; 1633*0Sstevel@tonic-gate } 1634*0Sstevel@tonic-gate my(@satts); 1635*0Sstevel@tonic-gate push(@satts,'src'=>$src) if $src; 1636*0Sstevel@tonic-gate push(@satts,'language'=>$language) unless defined $type; 1637*0Sstevel@tonic-gate push(@satts,'type'=>$type); 1638*0Sstevel@tonic-gate $code = "$cdata_start$code$cdata_end" if defined $code; 1639*0Sstevel@tonic-gate push(@result,script({@satts},$code || '')); 1640*0Sstevel@tonic-gate } 1641*0Sstevel@tonic-gate @result; 1642*0Sstevel@tonic-gate} 1643*0Sstevel@tonic-gateEND_OF_FUNC 1644*0Sstevel@tonic-gate 1645*0Sstevel@tonic-gate#### Method: end_html 1646*0Sstevel@tonic-gate# End an HTML document. 1647*0Sstevel@tonic-gate# Trivial method for completeness. Just returns "</body>" 1648*0Sstevel@tonic-gate#### 1649*0Sstevel@tonic-gate'end_html' => <<'END_OF_FUNC', 1650*0Sstevel@tonic-gatesub end_html { 1651*0Sstevel@tonic-gate return "</body></html>"; 1652*0Sstevel@tonic-gate} 1653*0Sstevel@tonic-gateEND_OF_FUNC 1654*0Sstevel@tonic-gate 1655*0Sstevel@tonic-gate 1656*0Sstevel@tonic-gate################################ 1657*0Sstevel@tonic-gate# METHODS USED IN BUILDING FORMS 1658*0Sstevel@tonic-gate################################ 1659*0Sstevel@tonic-gate 1660*0Sstevel@tonic-gate#### Method: isindex 1661*0Sstevel@tonic-gate# Just prints out the isindex tag. 1662*0Sstevel@tonic-gate# Parameters: 1663*0Sstevel@tonic-gate# $action -> optional URL of script to run 1664*0Sstevel@tonic-gate# Returns: 1665*0Sstevel@tonic-gate# A string containing a <isindex> tag 1666*0Sstevel@tonic-gate'isindex' => <<'END_OF_FUNC', 1667*0Sstevel@tonic-gatesub isindex { 1668*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 1669*0Sstevel@tonic-gate my($action,@other) = rearrange([ACTION],@p); 1670*0Sstevel@tonic-gate $action = qq/ action="$action"/ if $action; 1671*0Sstevel@tonic-gate my($other) = @other ? " @other" : ''; 1672*0Sstevel@tonic-gate return $XHTML ? "<isindex$action$other />" : "<isindex$action$other>"; 1673*0Sstevel@tonic-gate} 1674*0Sstevel@tonic-gateEND_OF_FUNC 1675*0Sstevel@tonic-gate 1676*0Sstevel@tonic-gate 1677*0Sstevel@tonic-gate#### Method: startform 1678*0Sstevel@tonic-gate# Start a form 1679*0Sstevel@tonic-gate# Parameters: 1680*0Sstevel@tonic-gate# $method -> optional submission method to use (GET or POST) 1681*0Sstevel@tonic-gate# $action -> optional URL of script to run 1682*0Sstevel@tonic-gate# $enctype ->encoding to use (URL_ENCODED or MULTIPART) 1683*0Sstevel@tonic-gate'startform' => <<'END_OF_FUNC', 1684*0Sstevel@tonic-gatesub startform { 1685*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 1686*0Sstevel@tonic-gate 1687*0Sstevel@tonic-gate my($method,$action,$enctype,@other) = 1688*0Sstevel@tonic-gate rearrange([METHOD,ACTION,ENCTYPE],@p); 1689*0Sstevel@tonic-gate 1690*0Sstevel@tonic-gate $method = lc($method) || 'post'; 1691*0Sstevel@tonic-gate $enctype = $enctype || &URL_ENCODED; 1692*0Sstevel@tonic-gate unless (defined $action) { 1693*0Sstevel@tonic-gate 1694*0Sstevel@tonic-gate $action = $self->escapeHTML($self->url(-absolute=>1,-path=>1)); 1695*0Sstevel@tonic-gate if (length($ENV{QUERY_STRING})>0) { 1696*0Sstevel@tonic-gate $action .= "?".$self->escapeHTML($ENV{QUERY_STRING},1); 1697*0Sstevel@tonic-gate } 1698*0Sstevel@tonic-gate } 1699*0Sstevel@tonic-gate $action = qq(action="$action"); 1700*0Sstevel@tonic-gate my($other) = @other ? " @other" : ''; 1701*0Sstevel@tonic-gate $self->{'.parametersToAdd'}={}; 1702*0Sstevel@tonic-gate return qq/<form method="$method" $action enctype="$enctype"$other>\n/; 1703*0Sstevel@tonic-gate} 1704*0Sstevel@tonic-gateEND_OF_FUNC 1705*0Sstevel@tonic-gate 1706*0Sstevel@tonic-gate 1707*0Sstevel@tonic-gate#### Method: start_form 1708*0Sstevel@tonic-gate# synonym for startform 1709*0Sstevel@tonic-gate'start_form' => <<'END_OF_FUNC', 1710*0Sstevel@tonic-gatesub start_form { 1711*0Sstevel@tonic-gate &startform; 1712*0Sstevel@tonic-gate} 1713*0Sstevel@tonic-gateEND_OF_FUNC 1714*0Sstevel@tonic-gate 1715*0Sstevel@tonic-gate'end_multipart_form' => <<'END_OF_FUNC', 1716*0Sstevel@tonic-gatesub end_multipart_form { 1717*0Sstevel@tonic-gate &endform; 1718*0Sstevel@tonic-gate} 1719*0Sstevel@tonic-gateEND_OF_FUNC 1720*0Sstevel@tonic-gate 1721*0Sstevel@tonic-gate#### Method: start_multipart_form 1722*0Sstevel@tonic-gate# synonym for startform 1723*0Sstevel@tonic-gate'start_multipart_form' => <<'END_OF_FUNC', 1724*0Sstevel@tonic-gatesub start_multipart_form { 1725*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 1726*0Sstevel@tonic-gate if (defined($param[0]) && substr($param[0],0,1) eq '-') { 1727*0Sstevel@tonic-gate my(%p) = @p; 1728*0Sstevel@tonic-gate $p{'-enctype'}=&MULTIPART; 1729*0Sstevel@tonic-gate return $self->startform(%p); 1730*0Sstevel@tonic-gate } else { 1731*0Sstevel@tonic-gate my($method,$action,@other) = 1732*0Sstevel@tonic-gate rearrange([METHOD,ACTION],@p); 1733*0Sstevel@tonic-gate return $self->startform($method,$action,&MULTIPART,@other); 1734*0Sstevel@tonic-gate } 1735*0Sstevel@tonic-gate} 1736*0Sstevel@tonic-gateEND_OF_FUNC 1737*0Sstevel@tonic-gate 1738*0Sstevel@tonic-gate 1739*0Sstevel@tonic-gate#### Method: endform 1740*0Sstevel@tonic-gate# End a form 1741*0Sstevel@tonic-gate'endform' => <<'END_OF_FUNC', 1742*0Sstevel@tonic-gatesub endform { 1743*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 1744*0Sstevel@tonic-gate if ( $NOSTICKY ) { 1745*0Sstevel@tonic-gate return wantarray ? ("</form>") : "\n</form>"; 1746*0Sstevel@tonic-gate } else { 1747*0Sstevel@tonic-gate return wantarray ? ("<div>",$self->get_fields,"</div>","</form>") : 1748*0Sstevel@tonic-gate "<div>".$self->get_fields ."</div>\n</form>"; 1749*0Sstevel@tonic-gate } 1750*0Sstevel@tonic-gate} 1751*0Sstevel@tonic-gateEND_OF_FUNC 1752*0Sstevel@tonic-gate 1753*0Sstevel@tonic-gate 1754*0Sstevel@tonic-gate#### Method: end_form 1755*0Sstevel@tonic-gate# synonym for endform 1756*0Sstevel@tonic-gate'end_form' => <<'END_OF_FUNC', 1757*0Sstevel@tonic-gatesub end_form { 1758*0Sstevel@tonic-gate &endform; 1759*0Sstevel@tonic-gate} 1760*0Sstevel@tonic-gateEND_OF_FUNC 1761*0Sstevel@tonic-gate 1762*0Sstevel@tonic-gate 1763*0Sstevel@tonic-gate'_textfield' => <<'END_OF_FUNC', 1764*0Sstevel@tonic-gatesub _textfield { 1765*0Sstevel@tonic-gate my($self,$tag,@p) = self_or_default(@_); 1766*0Sstevel@tonic-gate my($name,$default,$size,$maxlength,$override,@other) = 1767*0Sstevel@tonic-gate rearrange([NAME,[DEFAULT,VALUE,VALUES],SIZE,MAXLENGTH,[OVERRIDE,FORCE]],@p); 1768*0Sstevel@tonic-gate 1769*0Sstevel@tonic-gate my $current = $override ? $default : 1770*0Sstevel@tonic-gate (defined($self->param($name)) ? $self->param($name) : $default); 1771*0Sstevel@tonic-gate 1772*0Sstevel@tonic-gate $current = defined($current) ? $self->escapeHTML($current,1) : ''; 1773*0Sstevel@tonic-gate $name = defined($name) ? $self->escapeHTML($name) : ''; 1774*0Sstevel@tonic-gate my($s) = defined($size) ? qq/ size="$size"/ : ''; 1775*0Sstevel@tonic-gate my($m) = defined($maxlength) ? qq/ maxlength="$maxlength"/ : ''; 1776*0Sstevel@tonic-gate my($other) = @other ? " @other" : ''; 1777*0Sstevel@tonic-gate # this entered at cristy's request to fix problems with file upload fields 1778*0Sstevel@tonic-gate # and WebTV -- not sure it won't break stuff 1779*0Sstevel@tonic-gate my($value) = $current ne '' ? qq(value="$current") : ''; 1780*0Sstevel@tonic-gate return $XHTML ? qq(<input type="$tag" name="$name" $value$s$m$other />) 1781*0Sstevel@tonic-gate : qq(<input type="$tag" name="$name" $value$s$m$other>); 1782*0Sstevel@tonic-gate} 1783*0Sstevel@tonic-gateEND_OF_FUNC 1784*0Sstevel@tonic-gate 1785*0Sstevel@tonic-gate#### Method: textfield 1786*0Sstevel@tonic-gate# Parameters: 1787*0Sstevel@tonic-gate# $name -> Name of the text field 1788*0Sstevel@tonic-gate# $default -> Optional default value of the field if not 1789*0Sstevel@tonic-gate# already defined. 1790*0Sstevel@tonic-gate# $size -> Optional width of field in characaters. 1791*0Sstevel@tonic-gate# $maxlength -> Optional maximum number of characters. 1792*0Sstevel@tonic-gate# Returns: 1793*0Sstevel@tonic-gate# A string containing a <input type="text"> field 1794*0Sstevel@tonic-gate# 1795*0Sstevel@tonic-gate'textfield' => <<'END_OF_FUNC', 1796*0Sstevel@tonic-gatesub textfield { 1797*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 1798*0Sstevel@tonic-gate $self->_textfield('text',@p); 1799*0Sstevel@tonic-gate} 1800*0Sstevel@tonic-gateEND_OF_FUNC 1801*0Sstevel@tonic-gate 1802*0Sstevel@tonic-gate 1803*0Sstevel@tonic-gate#### Method: filefield 1804*0Sstevel@tonic-gate# Parameters: 1805*0Sstevel@tonic-gate# $name -> Name of the file upload field 1806*0Sstevel@tonic-gate# $size -> Optional width of field in characaters. 1807*0Sstevel@tonic-gate# $maxlength -> Optional maximum number of characters. 1808*0Sstevel@tonic-gate# Returns: 1809*0Sstevel@tonic-gate# A string containing a <input type="file"> field 1810*0Sstevel@tonic-gate# 1811*0Sstevel@tonic-gate'filefield' => <<'END_OF_FUNC', 1812*0Sstevel@tonic-gatesub filefield { 1813*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 1814*0Sstevel@tonic-gate $self->_textfield('file',@p); 1815*0Sstevel@tonic-gate} 1816*0Sstevel@tonic-gateEND_OF_FUNC 1817*0Sstevel@tonic-gate 1818*0Sstevel@tonic-gate 1819*0Sstevel@tonic-gate#### Method: password 1820*0Sstevel@tonic-gate# Create a "secret password" entry field 1821*0Sstevel@tonic-gate# Parameters: 1822*0Sstevel@tonic-gate# $name -> Name of the field 1823*0Sstevel@tonic-gate# $default -> Optional default value of the field if not 1824*0Sstevel@tonic-gate# already defined. 1825*0Sstevel@tonic-gate# $size -> Optional width of field in characters. 1826*0Sstevel@tonic-gate# $maxlength -> Optional maximum characters that can be entered. 1827*0Sstevel@tonic-gate# Returns: 1828*0Sstevel@tonic-gate# A string containing a <input type="password"> field 1829*0Sstevel@tonic-gate# 1830*0Sstevel@tonic-gate'password_field' => <<'END_OF_FUNC', 1831*0Sstevel@tonic-gatesub password_field { 1832*0Sstevel@tonic-gate my ($self,@p) = self_or_default(@_); 1833*0Sstevel@tonic-gate $self->_textfield('password',@p); 1834*0Sstevel@tonic-gate} 1835*0Sstevel@tonic-gateEND_OF_FUNC 1836*0Sstevel@tonic-gate 1837*0Sstevel@tonic-gate#### Method: textarea 1838*0Sstevel@tonic-gate# Parameters: 1839*0Sstevel@tonic-gate# $name -> Name of the text field 1840*0Sstevel@tonic-gate# $default -> Optional default value of the field if not 1841*0Sstevel@tonic-gate# already defined. 1842*0Sstevel@tonic-gate# $rows -> Optional number of rows in text area 1843*0Sstevel@tonic-gate# $columns -> Optional number of columns in text area 1844*0Sstevel@tonic-gate# Returns: 1845*0Sstevel@tonic-gate# A string containing a <textarea></textarea> tag 1846*0Sstevel@tonic-gate# 1847*0Sstevel@tonic-gate'textarea' => <<'END_OF_FUNC', 1848*0Sstevel@tonic-gatesub textarea { 1849*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 1850*0Sstevel@tonic-gate 1851*0Sstevel@tonic-gate my($name,$default,$rows,$cols,$override,@other) = 1852*0Sstevel@tonic-gate rearrange([NAME,[DEFAULT,VALUE],ROWS,[COLS,COLUMNS],[OVERRIDE,FORCE]],@p); 1853*0Sstevel@tonic-gate 1854*0Sstevel@tonic-gate my($current)= $override ? $default : 1855*0Sstevel@tonic-gate (defined($self->param($name)) ? $self->param($name) : $default); 1856*0Sstevel@tonic-gate 1857*0Sstevel@tonic-gate $name = defined($name) ? $self->escapeHTML($name) : ''; 1858*0Sstevel@tonic-gate $current = defined($current) ? $self->escapeHTML($current) : ''; 1859*0Sstevel@tonic-gate my($r) = $rows ? qq/ rows="$rows"/ : ''; 1860*0Sstevel@tonic-gate my($c) = $cols ? qq/ cols="$cols"/ : ''; 1861*0Sstevel@tonic-gate my($other) = @other ? " @other" : ''; 1862*0Sstevel@tonic-gate return qq{<textarea name="$name"$r$c$other>$current</textarea>}; 1863*0Sstevel@tonic-gate} 1864*0Sstevel@tonic-gateEND_OF_FUNC 1865*0Sstevel@tonic-gate 1866*0Sstevel@tonic-gate 1867*0Sstevel@tonic-gate#### Method: button 1868*0Sstevel@tonic-gate# Create a javascript button. 1869*0Sstevel@tonic-gate# Parameters: 1870*0Sstevel@tonic-gate# $name -> (optional) Name for the button. (-name) 1871*0Sstevel@tonic-gate# $value -> (optional) Value of the button when selected (and visible name) (-value) 1872*0Sstevel@tonic-gate# $onclick -> (optional) Text of the JavaScript to run when the button is 1873*0Sstevel@tonic-gate# clicked. 1874*0Sstevel@tonic-gate# Returns: 1875*0Sstevel@tonic-gate# A string containing a <input type="button"> tag 1876*0Sstevel@tonic-gate#### 1877*0Sstevel@tonic-gate'button' => <<'END_OF_FUNC', 1878*0Sstevel@tonic-gatesub button { 1879*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 1880*0Sstevel@tonic-gate 1881*0Sstevel@tonic-gate my($label,$value,$script,@other) = rearrange([NAME,[VALUE,LABEL], 1882*0Sstevel@tonic-gate [ONCLICK,SCRIPT]],@p); 1883*0Sstevel@tonic-gate 1884*0Sstevel@tonic-gate $label=$self->escapeHTML($label); 1885*0Sstevel@tonic-gate $value=$self->escapeHTML($value,1); 1886*0Sstevel@tonic-gate $script=$self->escapeHTML($script); 1887*0Sstevel@tonic-gate 1888*0Sstevel@tonic-gate my($name) = ''; 1889*0Sstevel@tonic-gate $name = qq/ name="$label"/ if $label; 1890*0Sstevel@tonic-gate $value = $value || $label; 1891*0Sstevel@tonic-gate my($val) = ''; 1892*0Sstevel@tonic-gate $val = qq/ value="$value"/ if $value; 1893*0Sstevel@tonic-gate $script = qq/ onclick="$script"/ if $script; 1894*0Sstevel@tonic-gate my($other) = @other ? " @other" : ''; 1895*0Sstevel@tonic-gate return $XHTML ? qq(<input type="button"$name$val$script$other />) 1896*0Sstevel@tonic-gate : qq(<input type="button"$name$val$script$other>); 1897*0Sstevel@tonic-gate} 1898*0Sstevel@tonic-gateEND_OF_FUNC 1899*0Sstevel@tonic-gate 1900*0Sstevel@tonic-gate 1901*0Sstevel@tonic-gate#### Method: submit 1902*0Sstevel@tonic-gate# Create a "submit query" button. 1903*0Sstevel@tonic-gate# Parameters: 1904*0Sstevel@tonic-gate# $name -> (optional) Name for the button. 1905*0Sstevel@tonic-gate# $value -> (optional) Value of the button when selected (also doubles as label). 1906*0Sstevel@tonic-gate# $label -> (optional) Label printed on the button(also doubles as the value). 1907*0Sstevel@tonic-gate# Returns: 1908*0Sstevel@tonic-gate# A string containing a <input type="submit"> tag 1909*0Sstevel@tonic-gate#### 1910*0Sstevel@tonic-gate'submit' => <<'END_OF_FUNC', 1911*0Sstevel@tonic-gatesub submit { 1912*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 1913*0Sstevel@tonic-gate 1914*0Sstevel@tonic-gate my($label,$value,@other) = rearrange([NAME,[VALUE,LABEL]],@p); 1915*0Sstevel@tonic-gate 1916*0Sstevel@tonic-gate $label=$self->escapeHTML($label); 1917*0Sstevel@tonic-gate $value=$self->escapeHTML($value,1); 1918*0Sstevel@tonic-gate 1919*0Sstevel@tonic-gate my $name = $NOSTICKY ? '' : ' name=".submit"'; 1920*0Sstevel@tonic-gate $name = qq/ name="$label"/ if defined($label); 1921*0Sstevel@tonic-gate $value = defined($value) ? $value : $label; 1922*0Sstevel@tonic-gate my $val = ''; 1923*0Sstevel@tonic-gate $val = qq/ value="$value"/ if defined($value); 1924*0Sstevel@tonic-gate my($other) = @other ? " @other" : ''; 1925*0Sstevel@tonic-gate return $XHTML ? qq(<input type="submit"$name$val$other />) 1926*0Sstevel@tonic-gate : qq(<input type="submit"$name$val$other>); 1927*0Sstevel@tonic-gate} 1928*0Sstevel@tonic-gateEND_OF_FUNC 1929*0Sstevel@tonic-gate 1930*0Sstevel@tonic-gate 1931*0Sstevel@tonic-gate#### Method: reset 1932*0Sstevel@tonic-gate# Create a "reset" button. 1933*0Sstevel@tonic-gate# Parameters: 1934*0Sstevel@tonic-gate# $name -> (optional) Name for the button. 1935*0Sstevel@tonic-gate# Returns: 1936*0Sstevel@tonic-gate# A string containing a <input type="reset"> tag 1937*0Sstevel@tonic-gate#### 1938*0Sstevel@tonic-gate'reset' => <<'END_OF_FUNC', 1939*0Sstevel@tonic-gatesub reset { 1940*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 1941*0Sstevel@tonic-gate my($label,$value,@other) = rearrange(['NAME',['VALUE','LABEL']],@p); 1942*0Sstevel@tonic-gate $label=$self->escapeHTML($label); 1943*0Sstevel@tonic-gate $value=$self->escapeHTML($value,1); 1944*0Sstevel@tonic-gate my ($name) = ' name=".reset"'; 1945*0Sstevel@tonic-gate $name = qq/ name="$label"/ if defined($label); 1946*0Sstevel@tonic-gate $value = defined($value) ? $value : $label; 1947*0Sstevel@tonic-gate my($val) = ''; 1948*0Sstevel@tonic-gate $val = qq/ value="$value"/ if defined($value); 1949*0Sstevel@tonic-gate my($other) = @other ? " @other" : ''; 1950*0Sstevel@tonic-gate return $XHTML ? qq(<input type="reset"$name$val$other />) 1951*0Sstevel@tonic-gate : qq(<input type="reset"$name$val$other>); 1952*0Sstevel@tonic-gate} 1953*0Sstevel@tonic-gateEND_OF_FUNC 1954*0Sstevel@tonic-gate 1955*0Sstevel@tonic-gate 1956*0Sstevel@tonic-gate#### Method: defaults 1957*0Sstevel@tonic-gate# Create a "defaults" button. 1958*0Sstevel@tonic-gate# Parameters: 1959*0Sstevel@tonic-gate# $name -> (optional) Name for the button. 1960*0Sstevel@tonic-gate# Returns: 1961*0Sstevel@tonic-gate# A string containing a <input type="submit" name=".defaults"> tag 1962*0Sstevel@tonic-gate# 1963*0Sstevel@tonic-gate# Note: this button has a special meaning to the initialization script, 1964*0Sstevel@tonic-gate# and tells it to ERASE the current query string so that your defaults 1965*0Sstevel@tonic-gate# are used again! 1966*0Sstevel@tonic-gate#### 1967*0Sstevel@tonic-gate'defaults' => <<'END_OF_FUNC', 1968*0Sstevel@tonic-gatesub defaults { 1969*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 1970*0Sstevel@tonic-gate 1971*0Sstevel@tonic-gate my($label,@other) = rearrange([[NAME,VALUE]],@p); 1972*0Sstevel@tonic-gate 1973*0Sstevel@tonic-gate $label=$self->escapeHTML($label,1); 1974*0Sstevel@tonic-gate $label = $label || "Defaults"; 1975*0Sstevel@tonic-gate my($value) = qq/ value="$label"/; 1976*0Sstevel@tonic-gate my($other) = @other ? " @other" : ''; 1977*0Sstevel@tonic-gate return $XHTML ? qq(<input type="submit" name=".defaults"$value$other />) 1978*0Sstevel@tonic-gate : qq/<input type="submit" NAME=".defaults"$value$other>/; 1979*0Sstevel@tonic-gate} 1980*0Sstevel@tonic-gateEND_OF_FUNC 1981*0Sstevel@tonic-gate 1982*0Sstevel@tonic-gate 1983*0Sstevel@tonic-gate#### Method: comment 1984*0Sstevel@tonic-gate# Create an HTML <!-- comment --> 1985*0Sstevel@tonic-gate# Parameters: a string 1986*0Sstevel@tonic-gate'comment' => <<'END_OF_FUNC', 1987*0Sstevel@tonic-gatesub comment { 1988*0Sstevel@tonic-gate my($self,@p) = self_or_CGI(@_); 1989*0Sstevel@tonic-gate return "<!-- @p -->"; 1990*0Sstevel@tonic-gate} 1991*0Sstevel@tonic-gateEND_OF_FUNC 1992*0Sstevel@tonic-gate 1993*0Sstevel@tonic-gate#### Method: checkbox 1994*0Sstevel@tonic-gate# Create a checkbox that is not logically linked to any others. 1995*0Sstevel@tonic-gate# The field value is "on" when the button is checked. 1996*0Sstevel@tonic-gate# Parameters: 1997*0Sstevel@tonic-gate# $name -> Name of the checkbox 1998*0Sstevel@tonic-gate# $checked -> (optional) turned on by default if true 1999*0Sstevel@tonic-gate# $value -> (optional) value of the checkbox, 'on' by default 2000*0Sstevel@tonic-gate# $label -> (optional) a user-readable label printed next to the box. 2001*0Sstevel@tonic-gate# Otherwise the checkbox name is used. 2002*0Sstevel@tonic-gate# Returns: 2003*0Sstevel@tonic-gate# A string containing a <input type="checkbox"> field 2004*0Sstevel@tonic-gate#### 2005*0Sstevel@tonic-gate'checkbox' => <<'END_OF_FUNC', 2006*0Sstevel@tonic-gatesub checkbox { 2007*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 2008*0Sstevel@tonic-gate 2009*0Sstevel@tonic-gate my($name,$checked,$value,$label,$override,@other) = 2010*0Sstevel@tonic-gate rearrange([NAME,[CHECKED,SELECTED,ON],VALUE,LABEL,[OVERRIDE,FORCE]],@p); 2011*0Sstevel@tonic-gate 2012*0Sstevel@tonic-gate $value = defined $value ? $value : 'on'; 2013*0Sstevel@tonic-gate 2014*0Sstevel@tonic-gate if (!$override && ($self->{'.fieldnames'}->{$name} || 2015*0Sstevel@tonic-gate defined $self->param($name))) { 2016*0Sstevel@tonic-gate $checked = grep($_ eq $value,$self->param($name)) ? $self->_checked(1) : ''; 2017*0Sstevel@tonic-gate } else { 2018*0Sstevel@tonic-gate $checked = $self->_checked($checked); 2019*0Sstevel@tonic-gate } 2020*0Sstevel@tonic-gate my($the_label) = defined $label ? $label : $name; 2021*0Sstevel@tonic-gate $name = $self->escapeHTML($name); 2022*0Sstevel@tonic-gate $value = $self->escapeHTML($value,1); 2023*0Sstevel@tonic-gate $the_label = $self->escapeHTML($the_label); 2024*0Sstevel@tonic-gate my($other) = @other ? " @other" : ''; 2025*0Sstevel@tonic-gate $self->register_parameter($name); 2026*0Sstevel@tonic-gate return $XHTML ? qq{<input type="checkbox" name="$name" value="$value"$checked$other />$the_label} 2027*0Sstevel@tonic-gate : qq{<input type="checkbox" name="$name" value="$value"$checked$other>$the_label}; 2028*0Sstevel@tonic-gate} 2029*0Sstevel@tonic-gateEND_OF_FUNC 2030*0Sstevel@tonic-gate 2031*0Sstevel@tonic-gate 2032*0Sstevel@tonic-gate#### Method: checkbox_group 2033*0Sstevel@tonic-gate# Create a list of logically-linked checkboxes. 2034*0Sstevel@tonic-gate# Parameters: 2035*0Sstevel@tonic-gate# $name -> Common name for all the check boxes 2036*0Sstevel@tonic-gate# $values -> A pointer to a regular array containing the 2037*0Sstevel@tonic-gate# values for each checkbox in the group. 2038*0Sstevel@tonic-gate# $defaults -> (optional) 2039*0Sstevel@tonic-gate# 1. If a pointer to a regular array of checkbox values, 2040*0Sstevel@tonic-gate# then this will be used to decide which 2041*0Sstevel@tonic-gate# checkboxes to turn on by default. 2042*0Sstevel@tonic-gate# 2. If a scalar, will be assumed to hold the 2043*0Sstevel@tonic-gate# value of a single checkbox in the group to turn on. 2044*0Sstevel@tonic-gate# $linebreak -> (optional) Set to true to place linebreaks 2045*0Sstevel@tonic-gate# between the buttons. 2046*0Sstevel@tonic-gate# $labels -> (optional) 2047*0Sstevel@tonic-gate# A pointer to an associative array of labels to print next to each checkbox 2048*0Sstevel@tonic-gate# in the form $label{'value'}="Long explanatory label". 2049*0Sstevel@tonic-gate# Otherwise the provided values are used as the labels. 2050*0Sstevel@tonic-gate# Returns: 2051*0Sstevel@tonic-gate# An ARRAY containing a series of <input type="checkbox"> fields 2052*0Sstevel@tonic-gate#### 2053*0Sstevel@tonic-gate'checkbox_group' => <<'END_OF_FUNC', 2054*0Sstevel@tonic-gatesub checkbox_group { 2055*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 2056*0Sstevel@tonic-gate 2057*0Sstevel@tonic-gate my($name,$values,$defaults,$linebreak,$labels,$attributes,$rows,$columns, 2058*0Sstevel@tonic-gate $rowheaders,$colheaders,$override,$nolabels,@other) = 2059*0Sstevel@tonic-gate rearrange([NAME,[VALUES,VALUE],[DEFAULTS,DEFAULT], 2060*0Sstevel@tonic-gate LINEBREAK,LABELS,ATTRIBUTES,ROWS,[COLUMNS,COLS], 2061*0Sstevel@tonic-gate ROWHEADERS,COLHEADERS, 2062*0Sstevel@tonic-gate [OVERRIDE,FORCE],NOLABELS],@p); 2063*0Sstevel@tonic-gate 2064*0Sstevel@tonic-gate my($checked,$break,$result,$label); 2065*0Sstevel@tonic-gate 2066*0Sstevel@tonic-gate my(%checked) = $self->previous_or_default($name,$defaults,$override); 2067*0Sstevel@tonic-gate 2068*0Sstevel@tonic-gate if ($linebreak) { 2069*0Sstevel@tonic-gate $break = $XHTML ? "<br />" : "<br>"; 2070*0Sstevel@tonic-gate } 2071*0Sstevel@tonic-gate else { 2072*0Sstevel@tonic-gate $break = ''; 2073*0Sstevel@tonic-gate } 2074*0Sstevel@tonic-gate $name=$self->escapeHTML($name); 2075*0Sstevel@tonic-gate 2076*0Sstevel@tonic-gate # Create the elements 2077*0Sstevel@tonic-gate my(@elements,@values); 2078*0Sstevel@tonic-gate 2079*0Sstevel@tonic-gate @values = $self->_set_values_and_labels($values,\$labels,$name); 2080*0Sstevel@tonic-gate 2081*0Sstevel@tonic-gate my($other) = @other ? " @other" : ''; 2082*0Sstevel@tonic-gate foreach (@values) { 2083*0Sstevel@tonic-gate $checked = $self->_checked($checked{$_}); 2084*0Sstevel@tonic-gate $label = ''; 2085*0Sstevel@tonic-gate unless (defined($nolabels) && $nolabels) { 2086*0Sstevel@tonic-gate $label = $_; 2087*0Sstevel@tonic-gate $label = $labels->{$_} if defined($labels) && defined($labels->{$_}); 2088*0Sstevel@tonic-gate $label = $self->escapeHTML($label); 2089*0Sstevel@tonic-gate } 2090*0Sstevel@tonic-gate my $attribs = $self->_set_attributes($_, $attributes); 2091*0Sstevel@tonic-gate $_ = $self->escapeHTML($_,1); 2092*0Sstevel@tonic-gate push(@elements,$XHTML ? qq(<input type="checkbox" name="$name" value="$_"$checked$other$attribs />${label}${break}) 2093*0Sstevel@tonic-gate : qq/<input type="checkbox" name="$name" value="$_"$checked$other$attribs>${label}${break}/); 2094*0Sstevel@tonic-gate } 2095*0Sstevel@tonic-gate $self->register_parameter($name); 2096*0Sstevel@tonic-gate return wantarray ? @elements : join(' ',@elements) 2097*0Sstevel@tonic-gate unless defined($columns) || defined($rows); 2098*0Sstevel@tonic-gate $rows = 1 if $rows && $rows < 1; 2099*0Sstevel@tonic-gate $cols = 1 if $cols && $cols < 1; 2100*0Sstevel@tonic-gate return _tableize($rows,$columns,$rowheaders,$colheaders,@elements); 2101*0Sstevel@tonic-gate} 2102*0Sstevel@tonic-gateEND_OF_FUNC 2103*0Sstevel@tonic-gate 2104*0Sstevel@tonic-gate# Escape HTML -- used internally 2105*0Sstevel@tonic-gate'escapeHTML' => <<'END_OF_FUNC', 2106*0Sstevel@tonic-gatesub escapeHTML { 2107*0Sstevel@tonic-gate # hack to work around earlier hacks 2108*0Sstevel@tonic-gate push @_,$_[0] if @_==1 && $_[0] eq 'CGI'; 2109*0Sstevel@tonic-gate my ($self,$toencode,$newlinestoo) = CGI::self_or_default(@_); 2110*0Sstevel@tonic-gate return undef unless defined($toencode); 2111*0Sstevel@tonic-gate return $toencode if ref($self) && !$self->{'escape'}; 2112*0Sstevel@tonic-gate $toencode =~ s{&}{&}gso; 2113*0Sstevel@tonic-gate $toencode =~ s{<}{<}gso; 2114*0Sstevel@tonic-gate $toencode =~ s{>}{>}gso; 2115*0Sstevel@tonic-gate $toencode =~ s{"}{"}gso; 2116*0Sstevel@tonic-gate my $latin = uc $self->{'.charset'} eq 'ISO-8859-1' || 2117*0Sstevel@tonic-gate uc $self->{'.charset'} eq 'WINDOWS-1252'; 2118*0Sstevel@tonic-gate if ($latin) { # bug in some browsers 2119*0Sstevel@tonic-gate $toencode =~ s{'}{'}gso; 2120*0Sstevel@tonic-gate $toencode =~ s{\x8b}{‹}gso; 2121*0Sstevel@tonic-gate $toencode =~ s{\x9b}{›}gso; 2122*0Sstevel@tonic-gate if (defined $newlinestoo && $newlinestoo) { 2123*0Sstevel@tonic-gate $toencode =~ s{\012}{ }gso; 2124*0Sstevel@tonic-gate $toencode =~ s{\015}{ }gso; 2125*0Sstevel@tonic-gate } 2126*0Sstevel@tonic-gate } 2127*0Sstevel@tonic-gate return $toencode; 2128*0Sstevel@tonic-gate} 2129*0Sstevel@tonic-gateEND_OF_FUNC 2130*0Sstevel@tonic-gate 2131*0Sstevel@tonic-gate# unescape HTML -- used internally 2132*0Sstevel@tonic-gate'unescapeHTML' => <<'END_OF_FUNC', 2133*0Sstevel@tonic-gatesub unescapeHTML { 2134*0Sstevel@tonic-gate # hack to work around earlier hacks 2135*0Sstevel@tonic-gate push @_,$_[0] if @_==1 && $_[0] eq 'CGI'; 2136*0Sstevel@tonic-gate my ($self,$string) = CGI::self_or_default(@_); 2137*0Sstevel@tonic-gate return undef unless defined($string); 2138*0Sstevel@tonic-gate my $latin = defined $self->{'.charset'} ? $self->{'.charset'} =~ /^(ISO-8859-1|WINDOWS-1252)$/i 2139*0Sstevel@tonic-gate : 1; 2140*0Sstevel@tonic-gate # thanks to Randal Schwartz for the correct solution to this one 2141*0Sstevel@tonic-gate $string=~ s[&(.*?);]{ 2142*0Sstevel@tonic-gate local $_ = $1; 2143*0Sstevel@tonic-gate /^amp$/i ? "&" : 2144*0Sstevel@tonic-gate /^quot$/i ? '"' : 2145*0Sstevel@tonic-gate /^gt$/i ? ">" : 2146*0Sstevel@tonic-gate /^lt$/i ? "<" : 2147*0Sstevel@tonic-gate /^#(\d+)$/ && $latin ? chr($1) : 2148*0Sstevel@tonic-gate /^#x([0-9a-f]+)$/i && $latin ? chr(hex($1)) : 2149*0Sstevel@tonic-gate $_ 2150*0Sstevel@tonic-gate }gex; 2151*0Sstevel@tonic-gate return $string; 2152*0Sstevel@tonic-gate} 2153*0Sstevel@tonic-gateEND_OF_FUNC 2154*0Sstevel@tonic-gate 2155*0Sstevel@tonic-gate# Internal procedure - don't use 2156*0Sstevel@tonic-gate'_tableize' => <<'END_OF_FUNC', 2157*0Sstevel@tonic-gatesub _tableize { 2158*0Sstevel@tonic-gate my($rows,$columns,$rowheaders,$colheaders,@elements) = @_; 2159*0Sstevel@tonic-gate $rowheaders = [] unless defined $rowheaders; 2160*0Sstevel@tonic-gate $colheaders = [] unless defined $colheaders; 2161*0Sstevel@tonic-gate my($result); 2162*0Sstevel@tonic-gate 2163*0Sstevel@tonic-gate if (defined($columns)) { 2164*0Sstevel@tonic-gate $rows = int(0.99 + @elements/$columns) unless defined($rows); 2165*0Sstevel@tonic-gate } 2166*0Sstevel@tonic-gate if (defined($rows)) { 2167*0Sstevel@tonic-gate $columns = int(0.99 + @elements/$rows) unless defined($columns); 2168*0Sstevel@tonic-gate } 2169*0Sstevel@tonic-gate 2170*0Sstevel@tonic-gate # rearrange into a pretty table 2171*0Sstevel@tonic-gate $result = "<table>"; 2172*0Sstevel@tonic-gate my($row,$column); 2173*0Sstevel@tonic-gate unshift(@$colheaders,'') if @$colheaders && @$rowheaders; 2174*0Sstevel@tonic-gate $result .= "<tr>" if @{$colheaders}; 2175*0Sstevel@tonic-gate foreach (@{$colheaders}) { 2176*0Sstevel@tonic-gate $result .= "<th>$_</th>"; 2177*0Sstevel@tonic-gate } 2178*0Sstevel@tonic-gate for ($row=0;$row<$rows;$row++) { 2179*0Sstevel@tonic-gate $result .= "<tr>"; 2180*0Sstevel@tonic-gate $result .= "<th>$rowheaders->[$row]</th>" if @$rowheaders; 2181*0Sstevel@tonic-gate for ($column=0;$column<$columns;$column++) { 2182*0Sstevel@tonic-gate $result .= "<td>" . $elements[$column*$rows + $row] . "</td>" 2183*0Sstevel@tonic-gate if defined($elements[$column*$rows + $row]); 2184*0Sstevel@tonic-gate } 2185*0Sstevel@tonic-gate $result .= "</tr>"; 2186*0Sstevel@tonic-gate } 2187*0Sstevel@tonic-gate $result .= "</table>"; 2188*0Sstevel@tonic-gate return $result; 2189*0Sstevel@tonic-gate} 2190*0Sstevel@tonic-gateEND_OF_FUNC 2191*0Sstevel@tonic-gate 2192*0Sstevel@tonic-gate 2193*0Sstevel@tonic-gate#### Method: radio_group 2194*0Sstevel@tonic-gate# Create a list of logically-linked radio buttons. 2195*0Sstevel@tonic-gate# Parameters: 2196*0Sstevel@tonic-gate# $name -> Common name for all the buttons. 2197*0Sstevel@tonic-gate# $values -> A pointer to a regular array containing the 2198*0Sstevel@tonic-gate# values for each button in the group. 2199*0Sstevel@tonic-gate# $default -> (optional) Value of the button to turn on by default. Pass '-' 2200*0Sstevel@tonic-gate# to turn _nothing_ on. 2201*0Sstevel@tonic-gate# $linebreak -> (optional) Set to true to place linebreaks 2202*0Sstevel@tonic-gate# between the buttons. 2203*0Sstevel@tonic-gate# $labels -> (optional) 2204*0Sstevel@tonic-gate# A pointer to an associative array of labels to print next to each checkbox 2205*0Sstevel@tonic-gate# in the form $label{'value'}="Long explanatory label". 2206*0Sstevel@tonic-gate# Otherwise the provided values are used as the labels. 2207*0Sstevel@tonic-gate# Returns: 2208*0Sstevel@tonic-gate# An ARRAY containing a series of <input type="radio"> fields 2209*0Sstevel@tonic-gate#### 2210*0Sstevel@tonic-gate'radio_group' => <<'END_OF_FUNC', 2211*0Sstevel@tonic-gatesub radio_group { 2212*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 2213*0Sstevel@tonic-gate 2214*0Sstevel@tonic-gate my($name,$values,$default,$linebreak,$labels,$attributes, 2215*0Sstevel@tonic-gate $rows,$columns,$rowheaders,$colheaders,$override,$nolabels,@other) = 2216*0Sstevel@tonic-gate rearrange([NAME,[VALUES,VALUE],DEFAULT,LINEBREAK,LABELS,ATTRIBUTES, 2217*0Sstevel@tonic-gate ROWS,[COLUMNS,COLS], 2218*0Sstevel@tonic-gate ROWHEADERS,COLHEADERS, 2219*0Sstevel@tonic-gate [OVERRIDE,FORCE],NOLABELS],@p); 2220*0Sstevel@tonic-gate my($result,$checked); 2221*0Sstevel@tonic-gate 2222*0Sstevel@tonic-gate if (!$override && defined($self->param($name))) { 2223*0Sstevel@tonic-gate $checked = $self->param($name); 2224*0Sstevel@tonic-gate } else { 2225*0Sstevel@tonic-gate $checked = $default; 2226*0Sstevel@tonic-gate } 2227*0Sstevel@tonic-gate my(@elements,@values); 2228*0Sstevel@tonic-gate @values = $self->_set_values_and_labels($values,\$labels,$name); 2229*0Sstevel@tonic-gate 2230*0Sstevel@tonic-gate # If no check array is specified, check the first by default 2231*0Sstevel@tonic-gate $checked = $values[0] unless defined($checked) && $checked ne ''; 2232*0Sstevel@tonic-gate $name=$self->escapeHTML($name); 2233*0Sstevel@tonic-gate 2234*0Sstevel@tonic-gate my($other) = @other ? " @other" : ''; 2235*0Sstevel@tonic-gate foreach (@values) { 2236*0Sstevel@tonic-gate my($checkit) = $checked eq $_ ? qq/ checked="checked"/ : ''; 2237*0Sstevel@tonic-gate my($break); 2238*0Sstevel@tonic-gate if ($linebreak) { 2239*0Sstevel@tonic-gate $break = $XHTML ? "<br />" : "<br>"; 2240*0Sstevel@tonic-gate } 2241*0Sstevel@tonic-gate else { 2242*0Sstevel@tonic-gate $break = ''; 2243*0Sstevel@tonic-gate } 2244*0Sstevel@tonic-gate my($label)=''; 2245*0Sstevel@tonic-gate unless (defined($nolabels) && $nolabels) { 2246*0Sstevel@tonic-gate $label = $_; 2247*0Sstevel@tonic-gate $label = $labels->{$_} if defined($labels) && defined($labels->{$_}); 2248*0Sstevel@tonic-gate $label = $self->escapeHTML($label,1); 2249*0Sstevel@tonic-gate } 2250*0Sstevel@tonic-gate my $attribs = $self->_set_attributes($_, $attributes); 2251*0Sstevel@tonic-gate $_=$self->escapeHTML($_); 2252*0Sstevel@tonic-gate push(@elements,$XHTML ? qq(<input type="radio" name="$name" value="$_"$checkit$other$attribs />${label}${break}) 2253*0Sstevel@tonic-gate : qq/<input type="radio" name="$name" value="$_"$checkit$other$attribs>${label}${break}/); 2254*0Sstevel@tonic-gate } 2255*0Sstevel@tonic-gate $self->register_parameter($name); 2256*0Sstevel@tonic-gate return wantarray ? @elements : join(' ',@elements) 2257*0Sstevel@tonic-gate unless defined($columns) || defined($rows); 2258*0Sstevel@tonic-gate return _tableize($rows,$columns,$rowheaders,$colheaders,@elements); 2259*0Sstevel@tonic-gate} 2260*0Sstevel@tonic-gateEND_OF_FUNC 2261*0Sstevel@tonic-gate 2262*0Sstevel@tonic-gate 2263*0Sstevel@tonic-gate#### Method: popup_menu 2264*0Sstevel@tonic-gate# Create a popup menu. 2265*0Sstevel@tonic-gate# Parameters: 2266*0Sstevel@tonic-gate# $name -> Name for all the menu 2267*0Sstevel@tonic-gate# $values -> A pointer to a regular array containing the 2268*0Sstevel@tonic-gate# text of each menu item. 2269*0Sstevel@tonic-gate# $default -> (optional) Default item to display 2270*0Sstevel@tonic-gate# $labels -> (optional) 2271*0Sstevel@tonic-gate# A pointer to an associative array of labels to print next to each checkbox 2272*0Sstevel@tonic-gate# in the form $label{'value'}="Long explanatory label". 2273*0Sstevel@tonic-gate# Otherwise the provided values are used as the labels. 2274*0Sstevel@tonic-gate# Returns: 2275*0Sstevel@tonic-gate# A string containing the definition of a popup menu. 2276*0Sstevel@tonic-gate#### 2277*0Sstevel@tonic-gate'popup_menu' => <<'END_OF_FUNC', 2278*0Sstevel@tonic-gatesub popup_menu { 2279*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 2280*0Sstevel@tonic-gate 2281*0Sstevel@tonic-gate my($name,$values,$default,$labels,$attributes,$override,@other) = 2282*0Sstevel@tonic-gate rearrange([NAME,[VALUES,VALUE],[DEFAULT,DEFAULTS],LABELS, 2283*0Sstevel@tonic-gate ATTRIBUTES,[OVERRIDE,FORCE]],@p); 2284*0Sstevel@tonic-gate my($result,$selected); 2285*0Sstevel@tonic-gate 2286*0Sstevel@tonic-gate if (!$override && defined($self->param($name))) { 2287*0Sstevel@tonic-gate $selected = $self->param($name); 2288*0Sstevel@tonic-gate } else { 2289*0Sstevel@tonic-gate $selected = $default; 2290*0Sstevel@tonic-gate } 2291*0Sstevel@tonic-gate $name=$self->escapeHTML($name); 2292*0Sstevel@tonic-gate my($other) = @other ? " @other" : ''; 2293*0Sstevel@tonic-gate 2294*0Sstevel@tonic-gate my(@values); 2295*0Sstevel@tonic-gate @values = $self->_set_values_and_labels($values,\$labels,$name); 2296*0Sstevel@tonic-gate 2297*0Sstevel@tonic-gate $result = qq/<select name="$name"$other>\n/; 2298*0Sstevel@tonic-gate foreach (@values) { 2299*0Sstevel@tonic-gate if (/<optgroup/) { 2300*0Sstevel@tonic-gate foreach (split(/\n/)) { 2301*0Sstevel@tonic-gate my $selectit = $XHTML ? 'selected="selected"' : 'selected'; 2302*0Sstevel@tonic-gate s/(value="$selected")/$selectit $1/ if defined $selected; 2303*0Sstevel@tonic-gate $result .= "$_\n"; 2304*0Sstevel@tonic-gate } 2305*0Sstevel@tonic-gate } 2306*0Sstevel@tonic-gate else { 2307*0Sstevel@tonic-gate my $attribs = $self->_set_attributes($_, $attributes); 2308*0Sstevel@tonic-gate my($selectit) = defined($selected) ? $self->_selected($selected eq $_) : ''; 2309*0Sstevel@tonic-gate my($label) = $_; 2310*0Sstevel@tonic-gate $label = $labels->{$_} if defined($labels) && defined($labels->{$_}); 2311*0Sstevel@tonic-gate my($value) = $self->escapeHTML($_); 2312*0Sstevel@tonic-gate $label=$self->escapeHTML($label,1); 2313*0Sstevel@tonic-gate $result .= "<option$selectit$attribs value=\"$value\">$label</option>\n"; 2314*0Sstevel@tonic-gate } 2315*0Sstevel@tonic-gate } 2316*0Sstevel@tonic-gate 2317*0Sstevel@tonic-gate $result .= "</select>"; 2318*0Sstevel@tonic-gate return $result; 2319*0Sstevel@tonic-gate} 2320*0Sstevel@tonic-gateEND_OF_FUNC 2321*0Sstevel@tonic-gate 2322*0Sstevel@tonic-gate 2323*0Sstevel@tonic-gate#### Method: optgroup 2324*0Sstevel@tonic-gate# Create a optgroup. 2325*0Sstevel@tonic-gate# Parameters: 2326*0Sstevel@tonic-gate# $name -> Label for the group 2327*0Sstevel@tonic-gate# $values -> A pointer to a regular array containing the 2328*0Sstevel@tonic-gate# values for each option line in the group. 2329*0Sstevel@tonic-gate# $labels -> (optional) 2330*0Sstevel@tonic-gate# A pointer to an associative array of labels to print next to each item 2331*0Sstevel@tonic-gate# in the form $label{'value'}="Long explanatory label". 2332*0Sstevel@tonic-gate# Otherwise the provided values are used as the labels. 2333*0Sstevel@tonic-gate# $labeled -> (optional) 2334*0Sstevel@tonic-gate# A true value indicates the value should be used as the label attribute 2335*0Sstevel@tonic-gate# in the option elements. 2336*0Sstevel@tonic-gate# The label attribute specifies the option label presented to the user. 2337*0Sstevel@tonic-gate# This defaults to the content of the <option> element, but the label 2338*0Sstevel@tonic-gate# attribute allows authors to more easily use optgroup without sacrificing 2339*0Sstevel@tonic-gate# compatibility with browsers that do not support option groups. 2340*0Sstevel@tonic-gate# $novals -> (optional) 2341*0Sstevel@tonic-gate# A true value indicates to suppress the val attribute in the option elements 2342*0Sstevel@tonic-gate# Returns: 2343*0Sstevel@tonic-gate# A string containing the definition of an option group. 2344*0Sstevel@tonic-gate#### 2345*0Sstevel@tonic-gate'optgroup' => <<'END_OF_FUNC', 2346*0Sstevel@tonic-gatesub optgroup { 2347*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 2348*0Sstevel@tonic-gate my($name,$values,$attributes,$labeled,$noval,$labels,@other) 2349*0Sstevel@tonic-gate = rearrange([NAME,[VALUES,VALUE],ATTRIBUTES,LABELED,NOVALS,LABELS],@p); 2350*0Sstevel@tonic-gate 2351*0Sstevel@tonic-gate my($result,@values); 2352*0Sstevel@tonic-gate @values = $self->_set_values_and_labels($values,\$labels,$name,$labeled,$novals); 2353*0Sstevel@tonic-gate my($other) = @other ? " @other" : ''; 2354*0Sstevel@tonic-gate 2355*0Sstevel@tonic-gate $name=$self->escapeHTML($name); 2356*0Sstevel@tonic-gate $result = qq/<optgroup label="$name"$other>\n/; 2357*0Sstevel@tonic-gate foreach (@values) { 2358*0Sstevel@tonic-gate if (/<optgroup/) { 2359*0Sstevel@tonic-gate foreach (split(/\n/)) { 2360*0Sstevel@tonic-gate my $selectit = $XHTML ? 'selected="selected"' : 'selected'; 2361*0Sstevel@tonic-gate s/(value="$selected")/$selectit $1/ if defined $selected; 2362*0Sstevel@tonic-gate $result .= "$_\n"; 2363*0Sstevel@tonic-gate } 2364*0Sstevel@tonic-gate } 2365*0Sstevel@tonic-gate else { 2366*0Sstevel@tonic-gate my $attribs = $self->_set_attributes($_, $attributes); 2367*0Sstevel@tonic-gate my($label) = $_; 2368*0Sstevel@tonic-gate $label = $labels->{$_} if defined($labels) && defined($labels->{$_}); 2369*0Sstevel@tonic-gate $label=$self->escapeHTML($label); 2370*0Sstevel@tonic-gate my($value)=$self->escapeHTML($_,1); 2371*0Sstevel@tonic-gate $result .= $labeled ? $novals ? "<option$attribs label=\"$value\">$label</option>\n" 2372*0Sstevel@tonic-gate : "<option$attribs label=\"$value\" value=\"$value\">$label</option>\n" 2373*0Sstevel@tonic-gate : $novals ? "<option$attribs>$label</option>\n" 2374*0Sstevel@tonic-gate : "<option$attribs value=\"$value\">$label</option>\n"; 2375*0Sstevel@tonic-gate } 2376*0Sstevel@tonic-gate } 2377*0Sstevel@tonic-gate $result .= "</optgroup>"; 2378*0Sstevel@tonic-gate return $result; 2379*0Sstevel@tonic-gate} 2380*0Sstevel@tonic-gateEND_OF_FUNC 2381*0Sstevel@tonic-gate 2382*0Sstevel@tonic-gate 2383*0Sstevel@tonic-gate#### Method: scrolling_list 2384*0Sstevel@tonic-gate# Create a scrolling list. 2385*0Sstevel@tonic-gate# Parameters: 2386*0Sstevel@tonic-gate# $name -> name for the list 2387*0Sstevel@tonic-gate# $values -> A pointer to a regular array containing the 2388*0Sstevel@tonic-gate# values for each option line in the list. 2389*0Sstevel@tonic-gate# $defaults -> (optional) 2390*0Sstevel@tonic-gate# 1. If a pointer to a regular array of options, 2391*0Sstevel@tonic-gate# then this will be used to decide which 2392*0Sstevel@tonic-gate# lines to turn on by default. 2393*0Sstevel@tonic-gate# 2. Otherwise holds the value of the single line to turn on. 2394*0Sstevel@tonic-gate# $size -> (optional) Size of the list. 2395*0Sstevel@tonic-gate# $multiple -> (optional) If set, allow multiple selections. 2396*0Sstevel@tonic-gate# $labels -> (optional) 2397*0Sstevel@tonic-gate# A pointer to an associative array of labels to print next to each checkbox 2398*0Sstevel@tonic-gate# in the form $label{'value'}="Long explanatory label". 2399*0Sstevel@tonic-gate# Otherwise the provided values are used as the labels. 2400*0Sstevel@tonic-gate# Returns: 2401*0Sstevel@tonic-gate# A string containing the definition of a scrolling list. 2402*0Sstevel@tonic-gate#### 2403*0Sstevel@tonic-gate'scrolling_list' => <<'END_OF_FUNC', 2404*0Sstevel@tonic-gatesub scrolling_list { 2405*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 2406*0Sstevel@tonic-gate my($name,$values,$defaults,$size,$multiple,$labels,$attributes,$override,@other) 2407*0Sstevel@tonic-gate = rearrange([NAME,[VALUES,VALUE],[DEFAULTS,DEFAULT], 2408*0Sstevel@tonic-gate SIZE,MULTIPLE,LABELS,ATTRIBUTES,[OVERRIDE,FORCE]],@p); 2409*0Sstevel@tonic-gate 2410*0Sstevel@tonic-gate my($result,@values); 2411*0Sstevel@tonic-gate @values = $self->_set_values_and_labels($values,\$labels,$name); 2412*0Sstevel@tonic-gate 2413*0Sstevel@tonic-gate $size = $size || scalar(@values); 2414*0Sstevel@tonic-gate 2415*0Sstevel@tonic-gate my(%selected) = $self->previous_or_default($name,$defaults,$override); 2416*0Sstevel@tonic-gate my($is_multiple) = $multiple ? qq/ multiple="multiple"/ : ''; 2417*0Sstevel@tonic-gate my($has_size) = $size ? qq/ size="$size"/: ''; 2418*0Sstevel@tonic-gate my($other) = @other ? " @other" : ''; 2419*0Sstevel@tonic-gate 2420*0Sstevel@tonic-gate $name=$self->escapeHTML($name); 2421*0Sstevel@tonic-gate $result = qq/<select name="$name"$has_size$is_multiple$other>\n/; 2422*0Sstevel@tonic-gate foreach (@values) { 2423*0Sstevel@tonic-gate my($selectit) = $self->_selected($selected{$_}); 2424*0Sstevel@tonic-gate my($label) = $_; 2425*0Sstevel@tonic-gate $label = $labels->{$_} if defined($labels) && defined($labels->{$_}); 2426*0Sstevel@tonic-gate $label=$self->escapeHTML($label); 2427*0Sstevel@tonic-gate my($value)=$self->escapeHTML($_,1); 2428*0Sstevel@tonic-gate my $attribs = $self->_set_attributes($_, $attributes); 2429*0Sstevel@tonic-gate $result .= "<option$selectit$attribs value=\"$value\">$label</option>\n"; 2430*0Sstevel@tonic-gate } 2431*0Sstevel@tonic-gate $result .= "</select>"; 2432*0Sstevel@tonic-gate $self->register_parameter($name); 2433*0Sstevel@tonic-gate return $result; 2434*0Sstevel@tonic-gate} 2435*0Sstevel@tonic-gateEND_OF_FUNC 2436*0Sstevel@tonic-gate 2437*0Sstevel@tonic-gate 2438*0Sstevel@tonic-gate#### Method: hidden 2439*0Sstevel@tonic-gate# Parameters: 2440*0Sstevel@tonic-gate# $name -> Name of the hidden field 2441*0Sstevel@tonic-gate# @default -> (optional) Initial values of field (may be an array) 2442*0Sstevel@tonic-gate# or 2443*0Sstevel@tonic-gate# $default->[initial values of field] 2444*0Sstevel@tonic-gate# Returns: 2445*0Sstevel@tonic-gate# A string containing a <input type="hidden" name="name" value="value"> 2446*0Sstevel@tonic-gate#### 2447*0Sstevel@tonic-gate'hidden' => <<'END_OF_FUNC', 2448*0Sstevel@tonic-gatesub hidden { 2449*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 2450*0Sstevel@tonic-gate 2451*0Sstevel@tonic-gate # this is the one place where we departed from our standard 2452*0Sstevel@tonic-gate # calling scheme, so we have to special-case (darn) 2453*0Sstevel@tonic-gate my(@result,@value); 2454*0Sstevel@tonic-gate my($name,$default,$override,@other) = 2455*0Sstevel@tonic-gate rearrange([NAME,[DEFAULT,VALUE,VALUES],[OVERRIDE,FORCE]],@p); 2456*0Sstevel@tonic-gate 2457*0Sstevel@tonic-gate my $do_override = 0; 2458*0Sstevel@tonic-gate if ( ref($p[0]) || substr($p[0],0,1) eq '-') { 2459*0Sstevel@tonic-gate @value = ref($default) ? @{$default} : $default; 2460*0Sstevel@tonic-gate $do_override = $override; 2461*0Sstevel@tonic-gate } else { 2462*0Sstevel@tonic-gate foreach ($default,$override,@other) { 2463*0Sstevel@tonic-gate push(@value,$_) if defined($_); 2464*0Sstevel@tonic-gate } 2465*0Sstevel@tonic-gate } 2466*0Sstevel@tonic-gate 2467*0Sstevel@tonic-gate # use previous values if override is not set 2468*0Sstevel@tonic-gate my @prev = $self->param($name); 2469*0Sstevel@tonic-gate @value = @prev if !$do_override && @prev; 2470*0Sstevel@tonic-gate 2471*0Sstevel@tonic-gate $name=$self->escapeHTML($name); 2472*0Sstevel@tonic-gate foreach (@value) { 2473*0Sstevel@tonic-gate $_ = defined($_) ? $self->escapeHTML($_,1) : ''; 2474*0Sstevel@tonic-gate push @result,$XHTML ? qq(<input type="hidden" name="$name" value="$_" />) 2475*0Sstevel@tonic-gate : qq(<input type="hidden" name="$name" value="$_">); 2476*0Sstevel@tonic-gate } 2477*0Sstevel@tonic-gate return wantarray ? @result : join('',@result); 2478*0Sstevel@tonic-gate} 2479*0Sstevel@tonic-gateEND_OF_FUNC 2480*0Sstevel@tonic-gate 2481*0Sstevel@tonic-gate 2482*0Sstevel@tonic-gate#### Method: image_button 2483*0Sstevel@tonic-gate# Parameters: 2484*0Sstevel@tonic-gate# $name -> Name of the button 2485*0Sstevel@tonic-gate# $src -> URL of the image source 2486*0Sstevel@tonic-gate# $align -> Alignment style (TOP, BOTTOM or MIDDLE) 2487*0Sstevel@tonic-gate# Returns: 2488*0Sstevel@tonic-gate# A string containing a <input type="image" name="name" src="url" align="alignment"> 2489*0Sstevel@tonic-gate#### 2490*0Sstevel@tonic-gate'image_button' => <<'END_OF_FUNC', 2491*0Sstevel@tonic-gatesub image_button { 2492*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 2493*0Sstevel@tonic-gate 2494*0Sstevel@tonic-gate my($name,$src,$alignment,@other) = 2495*0Sstevel@tonic-gate rearrange([NAME,SRC,ALIGN],@p); 2496*0Sstevel@tonic-gate 2497*0Sstevel@tonic-gate my($align) = $alignment ? " align=\U\"$alignment\"" : ''; 2498*0Sstevel@tonic-gate my($other) = @other ? " @other" : ''; 2499*0Sstevel@tonic-gate $name=$self->escapeHTML($name); 2500*0Sstevel@tonic-gate return $XHTML ? qq(<input type="image" name="$name" src="$src"$align$other />) 2501*0Sstevel@tonic-gate : qq/<input type="image" name="$name" src="$src"$align$other>/; 2502*0Sstevel@tonic-gate} 2503*0Sstevel@tonic-gateEND_OF_FUNC 2504*0Sstevel@tonic-gate 2505*0Sstevel@tonic-gate 2506*0Sstevel@tonic-gate#### Method: self_url 2507*0Sstevel@tonic-gate# Returns a URL containing the current script and all its 2508*0Sstevel@tonic-gate# param/value pairs arranged as a query. You can use this 2509*0Sstevel@tonic-gate# to create a link that, when selected, will reinvoke the 2510*0Sstevel@tonic-gate# script with all its state information preserved. 2511*0Sstevel@tonic-gate#### 2512*0Sstevel@tonic-gate'self_url' => <<'END_OF_FUNC', 2513*0Sstevel@tonic-gatesub self_url { 2514*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 2515*0Sstevel@tonic-gate return $self->url('-path_info'=>1,'-query'=>1,'-full'=>1,@p); 2516*0Sstevel@tonic-gate} 2517*0Sstevel@tonic-gateEND_OF_FUNC 2518*0Sstevel@tonic-gate 2519*0Sstevel@tonic-gate 2520*0Sstevel@tonic-gate# This is provided as a synonym to self_url() for people unfortunate 2521*0Sstevel@tonic-gate# enough to have incorporated it into their programs already! 2522*0Sstevel@tonic-gate'state' => <<'END_OF_FUNC', 2523*0Sstevel@tonic-gatesub state { 2524*0Sstevel@tonic-gate &self_url; 2525*0Sstevel@tonic-gate} 2526*0Sstevel@tonic-gateEND_OF_FUNC 2527*0Sstevel@tonic-gate 2528*0Sstevel@tonic-gate 2529*0Sstevel@tonic-gate#### Method: url 2530*0Sstevel@tonic-gate# Like self_url, but doesn't return the query string part of 2531*0Sstevel@tonic-gate# the URL. 2532*0Sstevel@tonic-gate#### 2533*0Sstevel@tonic-gate'url' => <<'END_OF_FUNC', 2534*0Sstevel@tonic-gatesub url { 2535*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 2536*0Sstevel@tonic-gate my ($relative,$absolute,$full,$path_info,$query,$base) = 2537*0Sstevel@tonic-gate rearrange(['RELATIVE','ABSOLUTE','FULL',['PATH','PATH_INFO'],['QUERY','QUERY_STRING'],'BASE'],@p); 2538*0Sstevel@tonic-gate my $url; 2539*0Sstevel@tonic-gate $full++ if $base || !($relative || $absolute); 2540*0Sstevel@tonic-gate 2541*0Sstevel@tonic-gate my $path = $self->path_info; 2542*0Sstevel@tonic-gate my $script_name = $self->script_name; 2543*0Sstevel@tonic-gate 2544*0Sstevel@tonic-gate # for compatibility with Apache's MultiViews 2545*0Sstevel@tonic-gate if (exists($ENV{REQUEST_URI})) { 2546*0Sstevel@tonic-gate my $index; 2547*0Sstevel@tonic-gate $script_name = unescape($ENV{REQUEST_URI}); 2548*0Sstevel@tonic-gate $script_name =~ s/\?.+$//; # strip query string 2549*0Sstevel@tonic-gate # and path 2550*0Sstevel@tonic-gate if (exists($ENV{PATH_INFO})) { 2551*0Sstevel@tonic-gate my $encoded_path = unescape($ENV{PATH_INFO}); 2552*0Sstevel@tonic-gate $script_name =~ s/\Q$encoded_path\E$//i; 2553*0Sstevel@tonic-gate } 2554*0Sstevel@tonic-gate } 2555*0Sstevel@tonic-gate 2556*0Sstevel@tonic-gate if ($full) { 2557*0Sstevel@tonic-gate my $protocol = $self->protocol(); 2558*0Sstevel@tonic-gate $url = "$protocol://"; 2559*0Sstevel@tonic-gate my $vh = http('host'); 2560*0Sstevel@tonic-gate if ($vh) { 2561*0Sstevel@tonic-gate $url .= $vh; 2562*0Sstevel@tonic-gate } else { 2563*0Sstevel@tonic-gate $url .= server_name(); 2564*0Sstevel@tonic-gate my $port = $self->server_port; 2565*0Sstevel@tonic-gate $url .= ":" . $port 2566*0Sstevel@tonic-gate unless (lc($protocol) eq 'http' && $port == 80) 2567*0Sstevel@tonic-gate || (lc($protocol) eq 'https' && $port == 443); 2568*0Sstevel@tonic-gate } 2569*0Sstevel@tonic-gate return $url if $base; 2570*0Sstevel@tonic-gate $url .= $script_name; 2571*0Sstevel@tonic-gate } elsif ($relative) { 2572*0Sstevel@tonic-gate ($url) = $script_name =~ m!([^/]+)$!; 2573*0Sstevel@tonic-gate } elsif ($absolute) { 2574*0Sstevel@tonic-gate $url = $script_name; 2575*0Sstevel@tonic-gate } 2576*0Sstevel@tonic-gate 2577*0Sstevel@tonic-gate $url .= $path if $path_info and defined $path; 2578*0Sstevel@tonic-gate $url .= "?" . $self->query_string if $query and $self->query_string; 2579*0Sstevel@tonic-gate $url = '' unless defined $url; 2580*0Sstevel@tonic-gate $url =~ s/([^a-zA-Z0-9_.%;&?\/\\:+=~-])/sprintf("%%%02X",ord($1))/eg; 2581*0Sstevel@tonic-gate return $url; 2582*0Sstevel@tonic-gate} 2583*0Sstevel@tonic-gate 2584*0Sstevel@tonic-gateEND_OF_FUNC 2585*0Sstevel@tonic-gate 2586*0Sstevel@tonic-gate#### Method: cookie 2587*0Sstevel@tonic-gate# Set or read a cookie from the specified name. 2588*0Sstevel@tonic-gate# Cookie can then be passed to header(). 2589*0Sstevel@tonic-gate# Usual rules apply to the stickiness of -value. 2590*0Sstevel@tonic-gate# Parameters: 2591*0Sstevel@tonic-gate# -name -> name for this cookie (optional) 2592*0Sstevel@tonic-gate# -value -> value of this cookie (scalar, array or hash) 2593*0Sstevel@tonic-gate# -path -> paths for which this cookie is valid (optional) 2594*0Sstevel@tonic-gate# -domain -> internet domain in which this cookie is valid (optional) 2595*0Sstevel@tonic-gate# -secure -> if true, cookie only passed through secure channel (optional) 2596*0Sstevel@tonic-gate# -expires -> expiry date in format Wdy, DD-Mon-YYYY HH:MM:SS GMT (optional) 2597*0Sstevel@tonic-gate#### 2598*0Sstevel@tonic-gate'cookie' => <<'END_OF_FUNC', 2599*0Sstevel@tonic-gatesub cookie { 2600*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 2601*0Sstevel@tonic-gate my($name,$value,$path,$domain,$secure,$expires) = 2602*0Sstevel@tonic-gate rearrange([NAME,[VALUE,VALUES],PATH,DOMAIN,SECURE,EXPIRES],@p); 2603*0Sstevel@tonic-gate 2604*0Sstevel@tonic-gate require CGI::Cookie; 2605*0Sstevel@tonic-gate 2606*0Sstevel@tonic-gate # if no value is supplied, then we retrieve the 2607*0Sstevel@tonic-gate # value of the cookie, if any. For efficiency, we cache the parsed 2608*0Sstevel@tonic-gate # cookies in our state variables. 2609*0Sstevel@tonic-gate unless ( defined($value) ) { 2610*0Sstevel@tonic-gate $self->{'.cookies'} = CGI::Cookie->fetch 2611*0Sstevel@tonic-gate unless $self->{'.cookies'}; 2612*0Sstevel@tonic-gate 2613*0Sstevel@tonic-gate # If no name is supplied, then retrieve the names of all our cookies. 2614*0Sstevel@tonic-gate return () unless $self->{'.cookies'}; 2615*0Sstevel@tonic-gate return keys %{$self->{'.cookies'}} unless $name; 2616*0Sstevel@tonic-gate return () unless $self->{'.cookies'}->{$name}; 2617*0Sstevel@tonic-gate return $self->{'.cookies'}->{$name}->value if defined($name) && $name ne ''; 2618*0Sstevel@tonic-gate } 2619*0Sstevel@tonic-gate 2620*0Sstevel@tonic-gate # If we get here, we're creating a new cookie 2621*0Sstevel@tonic-gate return undef unless defined($name) && $name ne ''; # this is an error 2622*0Sstevel@tonic-gate 2623*0Sstevel@tonic-gate my @param; 2624*0Sstevel@tonic-gate push(@param,'-name'=>$name); 2625*0Sstevel@tonic-gate push(@param,'-value'=>$value); 2626*0Sstevel@tonic-gate push(@param,'-domain'=>$domain) if $domain; 2627*0Sstevel@tonic-gate push(@param,'-path'=>$path) if $path; 2628*0Sstevel@tonic-gate push(@param,'-expires'=>$expires) if $expires; 2629*0Sstevel@tonic-gate push(@param,'-secure'=>$secure) if $secure; 2630*0Sstevel@tonic-gate 2631*0Sstevel@tonic-gate return new CGI::Cookie(@param); 2632*0Sstevel@tonic-gate} 2633*0Sstevel@tonic-gateEND_OF_FUNC 2634*0Sstevel@tonic-gate 2635*0Sstevel@tonic-gate'parse_keywordlist' => <<'END_OF_FUNC', 2636*0Sstevel@tonic-gatesub parse_keywordlist { 2637*0Sstevel@tonic-gate my($self,$tosplit) = @_; 2638*0Sstevel@tonic-gate $tosplit = unescape($tosplit); # unescape the keywords 2639*0Sstevel@tonic-gate $tosplit=~tr/+/ /; # pluses to spaces 2640*0Sstevel@tonic-gate my(@keywords) = split(/\s+/,$tosplit); 2641*0Sstevel@tonic-gate return @keywords; 2642*0Sstevel@tonic-gate} 2643*0Sstevel@tonic-gateEND_OF_FUNC 2644*0Sstevel@tonic-gate 2645*0Sstevel@tonic-gate'param_fetch' => <<'END_OF_FUNC', 2646*0Sstevel@tonic-gatesub param_fetch { 2647*0Sstevel@tonic-gate my($self,@p) = self_or_default(@_); 2648*0Sstevel@tonic-gate my($name) = rearrange([NAME],@p); 2649*0Sstevel@tonic-gate unless (exists($self->{$name})) { 2650*0Sstevel@tonic-gate $self->add_parameter($name); 2651*0Sstevel@tonic-gate $self->{$name} = []; 2652*0Sstevel@tonic-gate } 2653*0Sstevel@tonic-gate 2654*0Sstevel@tonic-gate return $self->{$name}; 2655*0Sstevel@tonic-gate} 2656*0Sstevel@tonic-gateEND_OF_FUNC 2657*0Sstevel@tonic-gate 2658*0Sstevel@tonic-gate############################################### 2659*0Sstevel@tonic-gate# OTHER INFORMATION PROVIDED BY THE ENVIRONMENT 2660*0Sstevel@tonic-gate############################################### 2661*0Sstevel@tonic-gate 2662*0Sstevel@tonic-gate#### Method: path_info 2663*0Sstevel@tonic-gate# Return the extra virtual path information provided 2664*0Sstevel@tonic-gate# after the URL (if any) 2665*0Sstevel@tonic-gate#### 2666*0Sstevel@tonic-gate'path_info' => <<'END_OF_FUNC', 2667*0Sstevel@tonic-gatesub path_info { 2668*0Sstevel@tonic-gate my ($self,$info) = self_or_default(@_); 2669*0Sstevel@tonic-gate if (defined($info)) { 2670*0Sstevel@tonic-gate $info = "/$info" if $info ne '' && substr($info,0,1) ne '/'; 2671*0Sstevel@tonic-gate $self->{'.path_info'} = $info; 2672*0Sstevel@tonic-gate } elsif (! defined($self->{'.path_info'}) ) { 2673*0Sstevel@tonic-gate $self->{'.path_info'} = defined($ENV{'PATH_INFO'}) ? 2674*0Sstevel@tonic-gate $ENV{'PATH_INFO'} : ''; 2675*0Sstevel@tonic-gate 2676*0Sstevel@tonic-gate # hack to fix broken path info in IIS 2677*0Sstevel@tonic-gate $self->{'.path_info'} =~ s/^\Q$ENV{'SCRIPT_NAME'}\E// if $IIS; 2678*0Sstevel@tonic-gate 2679*0Sstevel@tonic-gate } 2680*0Sstevel@tonic-gate return $self->{'.path_info'}; 2681*0Sstevel@tonic-gate} 2682*0Sstevel@tonic-gateEND_OF_FUNC 2683*0Sstevel@tonic-gate 2684*0Sstevel@tonic-gate 2685*0Sstevel@tonic-gate#### Method: request_method 2686*0Sstevel@tonic-gate# Returns 'POST', 'GET', 'PUT' or 'HEAD' 2687*0Sstevel@tonic-gate#### 2688*0Sstevel@tonic-gate'request_method' => <<'END_OF_FUNC', 2689*0Sstevel@tonic-gatesub request_method { 2690*0Sstevel@tonic-gate return $ENV{'REQUEST_METHOD'}; 2691*0Sstevel@tonic-gate} 2692*0Sstevel@tonic-gateEND_OF_FUNC 2693*0Sstevel@tonic-gate 2694*0Sstevel@tonic-gate#### Method: content_type 2695*0Sstevel@tonic-gate# Returns the content_type string 2696*0Sstevel@tonic-gate#### 2697*0Sstevel@tonic-gate'content_type' => <<'END_OF_FUNC', 2698*0Sstevel@tonic-gatesub content_type { 2699*0Sstevel@tonic-gate return $ENV{'CONTENT_TYPE'}; 2700*0Sstevel@tonic-gate} 2701*0Sstevel@tonic-gateEND_OF_FUNC 2702*0Sstevel@tonic-gate 2703*0Sstevel@tonic-gate#### Method: path_translated 2704*0Sstevel@tonic-gate# Return the physical path information provided 2705*0Sstevel@tonic-gate# by the URL (if any) 2706*0Sstevel@tonic-gate#### 2707*0Sstevel@tonic-gate'path_translated' => <<'END_OF_FUNC', 2708*0Sstevel@tonic-gatesub path_translated { 2709*0Sstevel@tonic-gate return $ENV{'PATH_TRANSLATED'}; 2710*0Sstevel@tonic-gate} 2711*0Sstevel@tonic-gateEND_OF_FUNC 2712*0Sstevel@tonic-gate 2713*0Sstevel@tonic-gate 2714*0Sstevel@tonic-gate#### Method: query_string 2715*0Sstevel@tonic-gate# Synthesize a query string from our current 2716*0Sstevel@tonic-gate# parameters 2717*0Sstevel@tonic-gate#### 2718*0Sstevel@tonic-gate'query_string' => <<'END_OF_FUNC', 2719*0Sstevel@tonic-gatesub query_string { 2720*0Sstevel@tonic-gate my($self) = self_or_default(@_); 2721*0Sstevel@tonic-gate my($param,$value,@pairs); 2722*0Sstevel@tonic-gate foreach $param ($self->param) { 2723*0Sstevel@tonic-gate my($eparam) = escape($param); 2724*0Sstevel@tonic-gate foreach $value ($self->param($param)) { 2725*0Sstevel@tonic-gate $value = escape($value); 2726*0Sstevel@tonic-gate next unless defined $value; 2727*0Sstevel@tonic-gate push(@pairs,"$eparam=$value"); 2728*0Sstevel@tonic-gate } 2729*0Sstevel@tonic-gate } 2730*0Sstevel@tonic-gate foreach (keys %{$self->{'.fieldnames'}}) { 2731*0Sstevel@tonic-gate push(@pairs,".cgifields=".escape("$_")); 2732*0Sstevel@tonic-gate } 2733*0Sstevel@tonic-gate return join($USE_PARAM_SEMICOLONS ? ';' : '&',@pairs); 2734*0Sstevel@tonic-gate} 2735*0Sstevel@tonic-gateEND_OF_FUNC 2736*0Sstevel@tonic-gate 2737*0Sstevel@tonic-gate 2738*0Sstevel@tonic-gate#### Method: accept 2739*0Sstevel@tonic-gate# Without parameters, returns an array of the 2740*0Sstevel@tonic-gate# MIME types the browser accepts. 2741*0Sstevel@tonic-gate# With a single parameter equal to a MIME 2742*0Sstevel@tonic-gate# type, will return undef if the browser won't 2743*0Sstevel@tonic-gate# accept it, 1 if the browser accepts it but 2744*0Sstevel@tonic-gate# doesn't give a preference, or a floating point 2745*0Sstevel@tonic-gate# value between 0.0 and 1.0 if the browser 2746*0Sstevel@tonic-gate# declares a quantitative score for it. 2747*0Sstevel@tonic-gate# This handles MIME type globs correctly. 2748*0Sstevel@tonic-gate#### 2749*0Sstevel@tonic-gate'Accept' => <<'END_OF_FUNC', 2750*0Sstevel@tonic-gatesub Accept { 2751*0Sstevel@tonic-gate my($self,$search) = self_or_CGI(@_); 2752*0Sstevel@tonic-gate my(%prefs,$type,$pref,$pat); 2753*0Sstevel@tonic-gate 2754*0Sstevel@tonic-gate my(@accept) = split(',',$self->http('accept')); 2755*0Sstevel@tonic-gate 2756*0Sstevel@tonic-gate foreach (@accept) { 2757*0Sstevel@tonic-gate ($pref) = /q=(\d\.\d+|\d+)/; 2758*0Sstevel@tonic-gate ($type) = m#(\S+/[^;]+)#; 2759*0Sstevel@tonic-gate next unless $type; 2760*0Sstevel@tonic-gate $prefs{$type}=$pref || 1; 2761*0Sstevel@tonic-gate } 2762*0Sstevel@tonic-gate 2763*0Sstevel@tonic-gate return keys %prefs unless $search; 2764*0Sstevel@tonic-gate 2765*0Sstevel@tonic-gate # if a search type is provided, we may need to 2766*0Sstevel@tonic-gate # perform a pattern matching operation. 2767*0Sstevel@tonic-gate # The MIME types use a glob mechanism, which 2768*0Sstevel@tonic-gate # is easily translated into a perl pattern match 2769*0Sstevel@tonic-gate 2770*0Sstevel@tonic-gate # First return the preference for directly supported 2771*0Sstevel@tonic-gate # types: 2772*0Sstevel@tonic-gate return $prefs{$search} if $prefs{$search}; 2773*0Sstevel@tonic-gate 2774*0Sstevel@tonic-gate # Didn't get it, so try pattern matching. 2775*0Sstevel@tonic-gate foreach (keys %prefs) { 2776*0Sstevel@tonic-gate next unless /\*/; # not a pattern match 2777*0Sstevel@tonic-gate ($pat = $_) =~ s/([^\w*])/\\$1/g; # escape meta characters 2778*0Sstevel@tonic-gate $pat =~ s/\*/.*/g; # turn it into a pattern 2779*0Sstevel@tonic-gate return $prefs{$_} if $search=~/$pat/; 2780*0Sstevel@tonic-gate } 2781*0Sstevel@tonic-gate} 2782*0Sstevel@tonic-gateEND_OF_FUNC 2783*0Sstevel@tonic-gate 2784*0Sstevel@tonic-gate 2785*0Sstevel@tonic-gate#### Method: user_agent 2786*0Sstevel@tonic-gate# If called with no parameters, returns the user agent. 2787*0Sstevel@tonic-gate# If called with one parameter, does a pattern match (case 2788*0Sstevel@tonic-gate# insensitive) on the user agent. 2789*0Sstevel@tonic-gate#### 2790*0Sstevel@tonic-gate'user_agent' => <<'END_OF_FUNC', 2791*0Sstevel@tonic-gatesub user_agent { 2792*0Sstevel@tonic-gate my($self,$match)=self_or_CGI(@_); 2793*0Sstevel@tonic-gate return $self->http('user_agent') unless $match; 2794*0Sstevel@tonic-gate return $self->http('user_agent') =~ /$match/i; 2795*0Sstevel@tonic-gate} 2796*0Sstevel@tonic-gateEND_OF_FUNC 2797*0Sstevel@tonic-gate 2798*0Sstevel@tonic-gate 2799*0Sstevel@tonic-gate#### Method: raw_cookie 2800*0Sstevel@tonic-gate# Returns the magic cookies for the session. 2801*0Sstevel@tonic-gate# The cookies are not parsed or altered in any way, i.e. 2802*0Sstevel@tonic-gate# cookies are returned exactly as given in the HTTP 2803*0Sstevel@tonic-gate# headers. If a cookie name is given, only that cookie's 2804*0Sstevel@tonic-gate# value is returned, otherwise the entire raw cookie 2805*0Sstevel@tonic-gate# is returned. 2806*0Sstevel@tonic-gate#### 2807*0Sstevel@tonic-gate'raw_cookie' => <<'END_OF_FUNC', 2808*0Sstevel@tonic-gatesub raw_cookie { 2809*0Sstevel@tonic-gate my($self,$key) = self_or_CGI(@_); 2810*0Sstevel@tonic-gate 2811*0Sstevel@tonic-gate require CGI::Cookie; 2812*0Sstevel@tonic-gate 2813*0Sstevel@tonic-gate if (defined($key)) { 2814*0Sstevel@tonic-gate $self->{'.raw_cookies'} = CGI::Cookie->raw_fetch 2815*0Sstevel@tonic-gate unless $self->{'.raw_cookies'}; 2816*0Sstevel@tonic-gate 2817*0Sstevel@tonic-gate return () unless $self->{'.raw_cookies'}; 2818*0Sstevel@tonic-gate return () unless $self->{'.raw_cookies'}->{$key}; 2819*0Sstevel@tonic-gate return $self->{'.raw_cookies'}->{$key}; 2820*0Sstevel@tonic-gate } 2821*0Sstevel@tonic-gate return $self->http('cookie') || $ENV{'COOKIE'} || ''; 2822*0Sstevel@tonic-gate} 2823*0Sstevel@tonic-gateEND_OF_FUNC 2824*0Sstevel@tonic-gate 2825*0Sstevel@tonic-gate#### Method: virtual_host 2826*0Sstevel@tonic-gate# Return the name of the virtual_host, which 2827*0Sstevel@tonic-gate# is not always the same as the server 2828*0Sstevel@tonic-gate###### 2829*0Sstevel@tonic-gate'virtual_host' => <<'END_OF_FUNC', 2830*0Sstevel@tonic-gatesub virtual_host { 2831*0Sstevel@tonic-gate my $vh = http('host') || server_name(); 2832*0Sstevel@tonic-gate $vh =~ s/:\d+$//; # get rid of port number 2833*0Sstevel@tonic-gate return $vh; 2834*0Sstevel@tonic-gate} 2835*0Sstevel@tonic-gateEND_OF_FUNC 2836*0Sstevel@tonic-gate 2837*0Sstevel@tonic-gate#### Method: remote_host 2838*0Sstevel@tonic-gate# Return the name of the remote host, or its IP 2839*0Sstevel@tonic-gate# address if unavailable. If this variable isn't 2840*0Sstevel@tonic-gate# defined, it returns "localhost" for debugging 2841*0Sstevel@tonic-gate# purposes. 2842*0Sstevel@tonic-gate#### 2843*0Sstevel@tonic-gate'remote_host' => <<'END_OF_FUNC', 2844*0Sstevel@tonic-gatesub remote_host { 2845*0Sstevel@tonic-gate return $ENV{'REMOTE_HOST'} || $ENV{'REMOTE_ADDR'} 2846*0Sstevel@tonic-gate || 'localhost'; 2847*0Sstevel@tonic-gate} 2848*0Sstevel@tonic-gateEND_OF_FUNC 2849*0Sstevel@tonic-gate 2850*0Sstevel@tonic-gate 2851*0Sstevel@tonic-gate#### Method: remote_addr 2852*0Sstevel@tonic-gate# Return the IP addr of the remote host. 2853*0Sstevel@tonic-gate#### 2854*0Sstevel@tonic-gate'remote_addr' => <<'END_OF_FUNC', 2855*0Sstevel@tonic-gatesub remote_addr { 2856*0Sstevel@tonic-gate return $ENV{'REMOTE_ADDR'} || '127.0.0.1'; 2857*0Sstevel@tonic-gate} 2858*0Sstevel@tonic-gateEND_OF_FUNC 2859*0Sstevel@tonic-gate 2860*0Sstevel@tonic-gate 2861*0Sstevel@tonic-gate#### Method: script_name 2862*0Sstevel@tonic-gate# Return the partial URL to this script for 2863*0Sstevel@tonic-gate# self-referencing scripts. Also see 2864*0Sstevel@tonic-gate# self_url(), which returns a URL with all state information 2865*0Sstevel@tonic-gate# preserved. 2866*0Sstevel@tonic-gate#### 2867*0Sstevel@tonic-gate'script_name' => <<'END_OF_FUNC', 2868*0Sstevel@tonic-gatesub script_name { 2869*0Sstevel@tonic-gate return $ENV{'SCRIPT_NAME'} if defined($ENV{'SCRIPT_NAME'}); 2870*0Sstevel@tonic-gate # These are for debugging 2871*0Sstevel@tonic-gate return "/$0" unless $0=~/^\//; 2872*0Sstevel@tonic-gate return $0; 2873*0Sstevel@tonic-gate} 2874*0Sstevel@tonic-gateEND_OF_FUNC 2875*0Sstevel@tonic-gate 2876*0Sstevel@tonic-gate 2877*0Sstevel@tonic-gate#### Method: referer 2878*0Sstevel@tonic-gate# Return the HTTP_REFERER: useful for generating 2879*0Sstevel@tonic-gate# a GO BACK button. 2880*0Sstevel@tonic-gate#### 2881*0Sstevel@tonic-gate'referer' => <<'END_OF_FUNC', 2882*0Sstevel@tonic-gatesub referer { 2883*0Sstevel@tonic-gate my($self) = self_or_CGI(@_); 2884*0Sstevel@tonic-gate return $self->http('referer'); 2885*0Sstevel@tonic-gate} 2886*0Sstevel@tonic-gateEND_OF_FUNC 2887*0Sstevel@tonic-gate 2888*0Sstevel@tonic-gate 2889*0Sstevel@tonic-gate#### Method: server_name 2890*0Sstevel@tonic-gate# Return the name of the server 2891*0Sstevel@tonic-gate#### 2892*0Sstevel@tonic-gate'server_name' => <<'END_OF_FUNC', 2893*0Sstevel@tonic-gatesub server_name { 2894*0Sstevel@tonic-gate return $ENV{'SERVER_NAME'} || 'localhost'; 2895*0Sstevel@tonic-gate} 2896*0Sstevel@tonic-gateEND_OF_FUNC 2897*0Sstevel@tonic-gate 2898*0Sstevel@tonic-gate#### Method: server_software 2899*0Sstevel@tonic-gate# Return the name of the server software 2900*0Sstevel@tonic-gate#### 2901*0Sstevel@tonic-gate'server_software' => <<'END_OF_FUNC', 2902*0Sstevel@tonic-gatesub server_software { 2903*0Sstevel@tonic-gate return $ENV{'SERVER_SOFTWARE'} || 'cmdline'; 2904*0Sstevel@tonic-gate} 2905*0Sstevel@tonic-gateEND_OF_FUNC 2906*0Sstevel@tonic-gate 2907*0Sstevel@tonic-gate#### Method: virtual_port 2908*0Sstevel@tonic-gate# Return the server port, taking virtual hosts into account 2909*0Sstevel@tonic-gate#### 2910*0Sstevel@tonic-gate'virtual_port' => <<'END_OF_FUNC', 2911*0Sstevel@tonic-gatesub virtual_port { 2912*0Sstevel@tonic-gate my($self) = self_or_default(@_); 2913*0Sstevel@tonic-gate my $vh = $self->http('host'); 2914*0Sstevel@tonic-gate if ($vh) { 2915*0Sstevel@tonic-gate return ($vh =~ /:(\d+)$/)[0] || '80'; 2916*0Sstevel@tonic-gate } else { 2917*0Sstevel@tonic-gate return $self->server_port(); 2918*0Sstevel@tonic-gate } 2919*0Sstevel@tonic-gate} 2920*0Sstevel@tonic-gateEND_OF_FUNC 2921*0Sstevel@tonic-gate 2922*0Sstevel@tonic-gate#### Method: server_port 2923*0Sstevel@tonic-gate# Return the tcp/ip port the server is running on 2924*0Sstevel@tonic-gate#### 2925*0Sstevel@tonic-gate'server_port' => <<'END_OF_FUNC', 2926*0Sstevel@tonic-gatesub server_port { 2927*0Sstevel@tonic-gate return $ENV{'SERVER_PORT'} || 80; # for debugging 2928*0Sstevel@tonic-gate} 2929*0Sstevel@tonic-gateEND_OF_FUNC 2930*0Sstevel@tonic-gate 2931*0Sstevel@tonic-gate#### Method: server_protocol 2932*0Sstevel@tonic-gate# Return the protocol (usually HTTP/1.0) 2933*0Sstevel@tonic-gate#### 2934*0Sstevel@tonic-gate'server_protocol' => <<'END_OF_FUNC', 2935*0Sstevel@tonic-gatesub server_protocol { 2936*0Sstevel@tonic-gate return $ENV{'SERVER_PROTOCOL'} || 'HTTP/1.0'; # for debugging 2937*0Sstevel@tonic-gate} 2938*0Sstevel@tonic-gateEND_OF_FUNC 2939*0Sstevel@tonic-gate 2940*0Sstevel@tonic-gate#### Method: http 2941*0Sstevel@tonic-gate# Return the value of an HTTP variable, or 2942*0Sstevel@tonic-gate# the list of variables if none provided 2943*0Sstevel@tonic-gate#### 2944*0Sstevel@tonic-gate'http' => <<'END_OF_FUNC', 2945*0Sstevel@tonic-gatesub http { 2946*0Sstevel@tonic-gate my ($self,$parameter) = self_or_CGI(@_); 2947*0Sstevel@tonic-gate return $ENV{$parameter} if $parameter=~/^HTTP/; 2948*0Sstevel@tonic-gate $parameter =~ tr/-/_/; 2949*0Sstevel@tonic-gate return $ENV{"HTTP_\U$parameter\E"} if $parameter; 2950*0Sstevel@tonic-gate my(@p); 2951*0Sstevel@tonic-gate foreach (keys %ENV) { 2952*0Sstevel@tonic-gate push(@p,$_) if /^HTTP/; 2953*0Sstevel@tonic-gate } 2954*0Sstevel@tonic-gate return @p; 2955*0Sstevel@tonic-gate} 2956*0Sstevel@tonic-gateEND_OF_FUNC 2957*0Sstevel@tonic-gate 2958*0Sstevel@tonic-gate#### Method: https 2959*0Sstevel@tonic-gate# Return the value of HTTPS 2960*0Sstevel@tonic-gate#### 2961*0Sstevel@tonic-gate'https' => <<'END_OF_FUNC', 2962*0Sstevel@tonic-gatesub https { 2963*0Sstevel@tonic-gate local($^W)=0; 2964*0Sstevel@tonic-gate my ($self,$parameter) = self_or_CGI(@_); 2965*0Sstevel@tonic-gate return $ENV{HTTPS} unless $parameter; 2966*0Sstevel@tonic-gate return $ENV{$parameter} if $parameter=~/^HTTPS/; 2967*0Sstevel@tonic-gate $parameter =~ tr/-/_/; 2968*0Sstevel@tonic-gate return $ENV{"HTTPS_\U$parameter\E"} if $parameter; 2969*0Sstevel@tonic-gate my(@p); 2970*0Sstevel@tonic-gate foreach (keys %ENV) { 2971*0Sstevel@tonic-gate push(@p,$_) if /^HTTPS/; 2972*0Sstevel@tonic-gate } 2973*0Sstevel@tonic-gate return @p; 2974*0Sstevel@tonic-gate} 2975*0Sstevel@tonic-gateEND_OF_FUNC 2976*0Sstevel@tonic-gate 2977*0Sstevel@tonic-gate#### Method: protocol 2978*0Sstevel@tonic-gate# Return the protocol (http or https currently) 2979*0Sstevel@tonic-gate#### 2980*0Sstevel@tonic-gate'protocol' => <<'END_OF_FUNC', 2981*0Sstevel@tonic-gatesub protocol { 2982*0Sstevel@tonic-gate local($^W)=0; 2983*0Sstevel@tonic-gate my $self = shift; 2984*0Sstevel@tonic-gate return 'https' if uc($self->https()) eq 'ON'; 2985*0Sstevel@tonic-gate return 'https' if $self->server_port == 443; 2986*0Sstevel@tonic-gate my $prot = $self->server_protocol; 2987*0Sstevel@tonic-gate my($protocol,$version) = split('/',$prot); 2988*0Sstevel@tonic-gate return "\L$protocol\E"; 2989*0Sstevel@tonic-gate} 2990*0Sstevel@tonic-gateEND_OF_FUNC 2991*0Sstevel@tonic-gate 2992*0Sstevel@tonic-gate#### Method: remote_ident 2993*0Sstevel@tonic-gate# Return the identity of the remote user 2994*0Sstevel@tonic-gate# (but only if his host is running identd) 2995*0Sstevel@tonic-gate#### 2996*0Sstevel@tonic-gate'remote_ident' => <<'END_OF_FUNC', 2997*0Sstevel@tonic-gatesub remote_ident { 2998*0Sstevel@tonic-gate return $ENV{'REMOTE_IDENT'}; 2999*0Sstevel@tonic-gate} 3000*0Sstevel@tonic-gateEND_OF_FUNC 3001*0Sstevel@tonic-gate 3002*0Sstevel@tonic-gate 3003*0Sstevel@tonic-gate#### Method: auth_type 3004*0Sstevel@tonic-gate# Return the type of use verification/authorization in use, if any. 3005*0Sstevel@tonic-gate#### 3006*0Sstevel@tonic-gate'auth_type' => <<'END_OF_FUNC', 3007*0Sstevel@tonic-gatesub auth_type { 3008*0Sstevel@tonic-gate return $ENV{'AUTH_TYPE'}; 3009*0Sstevel@tonic-gate} 3010*0Sstevel@tonic-gateEND_OF_FUNC 3011*0Sstevel@tonic-gate 3012*0Sstevel@tonic-gate 3013*0Sstevel@tonic-gate#### Method: remote_user 3014*0Sstevel@tonic-gate# Return the authorization name used for user 3015*0Sstevel@tonic-gate# verification. 3016*0Sstevel@tonic-gate#### 3017*0Sstevel@tonic-gate'remote_user' => <<'END_OF_FUNC', 3018*0Sstevel@tonic-gatesub remote_user { 3019*0Sstevel@tonic-gate return $ENV{'REMOTE_USER'}; 3020*0Sstevel@tonic-gate} 3021*0Sstevel@tonic-gateEND_OF_FUNC 3022*0Sstevel@tonic-gate 3023*0Sstevel@tonic-gate 3024*0Sstevel@tonic-gate#### Method: user_name 3025*0Sstevel@tonic-gate# Try to return the remote user's name by hook or by 3026*0Sstevel@tonic-gate# crook 3027*0Sstevel@tonic-gate#### 3028*0Sstevel@tonic-gate'user_name' => <<'END_OF_FUNC', 3029*0Sstevel@tonic-gatesub user_name { 3030*0Sstevel@tonic-gate my ($self) = self_or_CGI(@_); 3031*0Sstevel@tonic-gate return $self->http('from') || $ENV{'REMOTE_IDENT'} || $ENV{'REMOTE_USER'}; 3032*0Sstevel@tonic-gate} 3033*0Sstevel@tonic-gateEND_OF_FUNC 3034*0Sstevel@tonic-gate 3035*0Sstevel@tonic-gate#### Method: nosticky 3036*0Sstevel@tonic-gate# Set or return the NOSTICKY global flag 3037*0Sstevel@tonic-gate#### 3038*0Sstevel@tonic-gate'nosticky' => <<'END_OF_FUNC', 3039*0Sstevel@tonic-gatesub nosticky { 3040*0Sstevel@tonic-gate my ($self,$param) = self_or_CGI(@_); 3041*0Sstevel@tonic-gate $CGI::NOSTICKY = $param if defined($param); 3042*0Sstevel@tonic-gate return $CGI::NOSTICKY; 3043*0Sstevel@tonic-gate} 3044*0Sstevel@tonic-gateEND_OF_FUNC 3045*0Sstevel@tonic-gate 3046*0Sstevel@tonic-gate#### Method: nph 3047*0Sstevel@tonic-gate# Set or return the NPH global flag 3048*0Sstevel@tonic-gate#### 3049*0Sstevel@tonic-gate'nph' => <<'END_OF_FUNC', 3050*0Sstevel@tonic-gatesub nph { 3051*0Sstevel@tonic-gate my ($self,$param) = self_or_CGI(@_); 3052*0Sstevel@tonic-gate $CGI::NPH = $param if defined($param); 3053*0Sstevel@tonic-gate return $CGI::NPH; 3054*0Sstevel@tonic-gate} 3055*0Sstevel@tonic-gateEND_OF_FUNC 3056*0Sstevel@tonic-gate 3057*0Sstevel@tonic-gate#### Method: private_tempfiles 3058*0Sstevel@tonic-gate# Set or return the private_tempfiles global flag 3059*0Sstevel@tonic-gate#### 3060*0Sstevel@tonic-gate'private_tempfiles' => <<'END_OF_FUNC', 3061*0Sstevel@tonic-gatesub private_tempfiles { 3062*0Sstevel@tonic-gate my ($self,$param) = self_or_CGI(@_); 3063*0Sstevel@tonic-gate $CGI::PRIVATE_TEMPFILES = $param if defined($param); 3064*0Sstevel@tonic-gate return $CGI::PRIVATE_TEMPFILES; 3065*0Sstevel@tonic-gate} 3066*0Sstevel@tonic-gateEND_OF_FUNC 3067*0Sstevel@tonic-gate#### Method: close_upload_files 3068*0Sstevel@tonic-gate# Set or return the close_upload_files global flag 3069*0Sstevel@tonic-gate#### 3070*0Sstevel@tonic-gate'close_upload_files' => <<'END_OF_FUNC', 3071*0Sstevel@tonic-gatesub close_upload_files { 3072*0Sstevel@tonic-gate my ($self,$param) = self_or_CGI(@_); 3073*0Sstevel@tonic-gate $CGI::CLOSE_UPLOAD_FILES = $param if defined($param); 3074*0Sstevel@tonic-gate return $CGI::CLOSE_UPLOAD_FILES; 3075*0Sstevel@tonic-gate} 3076*0Sstevel@tonic-gateEND_OF_FUNC 3077*0Sstevel@tonic-gate 3078*0Sstevel@tonic-gate 3079*0Sstevel@tonic-gate#### Method: default_dtd 3080*0Sstevel@tonic-gate# Set or return the default_dtd global 3081*0Sstevel@tonic-gate#### 3082*0Sstevel@tonic-gate'default_dtd' => <<'END_OF_FUNC', 3083*0Sstevel@tonic-gatesub default_dtd { 3084*0Sstevel@tonic-gate my ($self,$param,$param2) = self_or_CGI(@_); 3085*0Sstevel@tonic-gate if (defined $param2 && defined $param) { 3086*0Sstevel@tonic-gate $CGI::DEFAULT_DTD = [ $param, $param2 ]; 3087*0Sstevel@tonic-gate } elsif (defined $param) { 3088*0Sstevel@tonic-gate $CGI::DEFAULT_DTD = $param; 3089*0Sstevel@tonic-gate } 3090*0Sstevel@tonic-gate return $CGI::DEFAULT_DTD; 3091*0Sstevel@tonic-gate} 3092*0Sstevel@tonic-gateEND_OF_FUNC 3093*0Sstevel@tonic-gate 3094*0Sstevel@tonic-gate# -------------- really private subroutines ----------------- 3095*0Sstevel@tonic-gate'previous_or_default' => <<'END_OF_FUNC', 3096*0Sstevel@tonic-gatesub previous_or_default { 3097*0Sstevel@tonic-gate my($self,$name,$defaults,$override) = @_; 3098*0Sstevel@tonic-gate my(%selected); 3099*0Sstevel@tonic-gate 3100*0Sstevel@tonic-gate if (!$override && ($self->{'.fieldnames'}->{$name} || 3101*0Sstevel@tonic-gate defined($self->param($name)) ) ) { 3102*0Sstevel@tonic-gate grep($selected{$_}++,$self->param($name)); 3103*0Sstevel@tonic-gate } elsif (defined($defaults) && ref($defaults) && 3104*0Sstevel@tonic-gate (ref($defaults) eq 'ARRAY')) { 3105*0Sstevel@tonic-gate grep($selected{$_}++,@{$defaults}); 3106*0Sstevel@tonic-gate } else { 3107*0Sstevel@tonic-gate $selected{$defaults}++ if defined($defaults); 3108*0Sstevel@tonic-gate } 3109*0Sstevel@tonic-gate 3110*0Sstevel@tonic-gate return %selected; 3111*0Sstevel@tonic-gate} 3112*0Sstevel@tonic-gateEND_OF_FUNC 3113*0Sstevel@tonic-gate 3114*0Sstevel@tonic-gate'register_parameter' => <<'END_OF_FUNC', 3115*0Sstevel@tonic-gatesub register_parameter { 3116*0Sstevel@tonic-gate my($self,$param) = @_; 3117*0Sstevel@tonic-gate $self->{'.parametersToAdd'}->{$param}++; 3118*0Sstevel@tonic-gate} 3119*0Sstevel@tonic-gateEND_OF_FUNC 3120*0Sstevel@tonic-gate 3121*0Sstevel@tonic-gate'get_fields' => <<'END_OF_FUNC', 3122*0Sstevel@tonic-gatesub get_fields { 3123*0Sstevel@tonic-gate my($self) = @_; 3124*0Sstevel@tonic-gate return $self->CGI::hidden('-name'=>'.cgifields', 3125*0Sstevel@tonic-gate '-values'=>[keys %{$self->{'.parametersToAdd'}}], 3126*0Sstevel@tonic-gate '-override'=>1); 3127*0Sstevel@tonic-gate} 3128*0Sstevel@tonic-gateEND_OF_FUNC 3129*0Sstevel@tonic-gate 3130*0Sstevel@tonic-gate'read_from_cmdline' => <<'END_OF_FUNC', 3131*0Sstevel@tonic-gatesub read_from_cmdline { 3132*0Sstevel@tonic-gate my($input,@words); 3133*0Sstevel@tonic-gate my($query_string); 3134*0Sstevel@tonic-gate my($subpath); 3135*0Sstevel@tonic-gate if ($DEBUG && @ARGV) { 3136*0Sstevel@tonic-gate @words = @ARGV; 3137*0Sstevel@tonic-gate } elsif ($DEBUG > 1) { 3138*0Sstevel@tonic-gate require "shellwords.pl"; 3139*0Sstevel@tonic-gate print STDERR "(offline mode: enter name=value pairs on standard input; press ^D or ^Z when done)\n"; 3140*0Sstevel@tonic-gate chomp(@lines = <STDIN>); # remove newlines 3141*0Sstevel@tonic-gate $input = join(" ",@lines); 3142*0Sstevel@tonic-gate @words = &shellwords($input); 3143*0Sstevel@tonic-gate } 3144*0Sstevel@tonic-gate foreach (@words) { 3145*0Sstevel@tonic-gate s/\\=/%3D/g; 3146*0Sstevel@tonic-gate s/\\&/%26/g; 3147*0Sstevel@tonic-gate } 3148*0Sstevel@tonic-gate 3149*0Sstevel@tonic-gate if ("@words"=~/=/) { 3150*0Sstevel@tonic-gate $query_string = join('&',@words); 3151*0Sstevel@tonic-gate } else { 3152*0Sstevel@tonic-gate $query_string = join('+',@words); 3153*0Sstevel@tonic-gate } 3154*0Sstevel@tonic-gate if ($query_string =~ /^(.*?)\?(.*)$/) 3155*0Sstevel@tonic-gate { 3156*0Sstevel@tonic-gate $query_string = $2; 3157*0Sstevel@tonic-gate $subpath = $1; 3158*0Sstevel@tonic-gate } 3159*0Sstevel@tonic-gate return { 'query_string' => $query_string, 'subpath' => $subpath }; 3160*0Sstevel@tonic-gate} 3161*0Sstevel@tonic-gateEND_OF_FUNC 3162*0Sstevel@tonic-gate 3163*0Sstevel@tonic-gate##### 3164*0Sstevel@tonic-gate# subroutine: read_multipart 3165*0Sstevel@tonic-gate# 3166*0Sstevel@tonic-gate# Read multipart data and store it into our parameters. 3167*0Sstevel@tonic-gate# An interesting feature is that if any of the parts is a file, we 3168*0Sstevel@tonic-gate# create a temporary file and open up a filehandle on it so that the 3169*0Sstevel@tonic-gate# caller can read from it if necessary. 3170*0Sstevel@tonic-gate##### 3171*0Sstevel@tonic-gate'read_multipart' => <<'END_OF_FUNC', 3172*0Sstevel@tonic-gatesub read_multipart { 3173*0Sstevel@tonic-gate my($self,$boundary,$length) = @_; 3174*0Sstevel@tonic-gate my($buffer) = $self->new_MultipartBuffer($boundary,$length); 3175*0Sstevel@tonic-gate return unless $buffer; 3176*0Sstevel@tonic-gate my(%header,$body); 3177*0Sstevel@tonic-gate my $filenumber = 0; 3178*0Sstevel@tonic-gate while (!$buffer->eof) { 3179*0Sstevel@tonic-gate %header = $buffer->readHeader; 3180*0Sstevel@tonic-gate 3181*0Sstevel@tonic-gate unless (%header) { 3182*0Sstevel@tonic-gate $self->cgi_error("400 Bad request (malformed multipart POST)"); 3183*0Sstevel@tonic-gate return; 3184*0Sstevel@tonic-gate } 3185*0Sstevel@tonic-gate 3186*0Sstevel@tonic-gate my($param)= $header{'Content-Disposition'}=~/ name="?([^\";]*)"?/; 3187*0Sstevel@tonic-gate $param .= $TAINTED; 3188*0Sstevel@tonic-gate 3189*0Sstevel@tonic-gate # Bug: Netscape doesn't escape quotation marks in file names!!! 3190*0Sstevel@tonic-gate my($filename) = $header{'Content-Disposition'}=~/ filename="?([^\"]*)"?/; 3191*0Sstevel@tonic-gate # Test for Opera's multiple upload feature 3192*0Sstevel@tonic-gate my($multipart) = ( defined( $header{'Content-Type'} ) && 3193*0Sstevel@tonic-gate $header{'Content-Type'} =~ /multipart\/mixed/ ) ? 3194*0Sstevel@tonic-gate 1 : 0; 3195*0Sstevel@tonic-gate 3196*0Sstevel@tonic-gate # add this parameter to our list 3197*0Sstevel@tonic-gate $self->add_parameter($param); 3198*0Sstevel@tonic-gate 3199*0Sstevel@tonic-gate # If no filename specified, then just read the data and assign it 3200*0Sstevel@tonic-gate # to our parameter list. 3201*0Sstevel@tonic-gate if ( ( !defined($filename) || $filename eq '' ) && !$multipart ) { 3202*0Sstevel@tonic-gate my($value) = $buffer->readBody; 3203*0Sstevel@tonic-gate $value .= $TAINTED; 3204*0Sstevel@tonic-gate push(@{$self->{$param}},$value); 3205*0Sstevel@tonic-gate next; 3206*0Sstevel@tonic-gate } 3207*0Sstevel@tonic-gate 3208*0Sstevel@tonic-gate my ($tmpfile,$tmp,$filehandle); 3209*0Sstevel@tonic-gate UPLOADS: { 3210*0Sstevel@tonic-gate # If we get here, then we are dealing with a potentially large 3211*0Sstevel@tonic-gate # uploaded form. Save the data to a temporary file, then open 3212*0Sstevel@tonic-gate # the file for reading. 3213*0Sstevel@tonic-gate 3214*0Sstevel@tonic-gate # skip the file if uploads disabled 3215*0Sstevel@tonic-gate if ($DISABLE_UPLOADS) { 3216*0Sstevel@tonic-gate while (defined($data = $buffer->read)) { } 3217*0Sstevel@tonic-gate last UPLOADS; 3218*0Sstevel@tonic-gate } 3219*0Sstevel@tonic-gate 3220*0Sstevel@tonic-gate # set the filename to some recognizable value 3221*0Sstevel@tonic-gate if ( ( !defined($filename) || $filename eq '' ) && $multipart ) { 3222*0Sstevel@tonic-gate $filename = "multipart/mixed"; 3223*0Sstevel@tonic-gate } 3224*0Sstevel@tonic-gate 3225*0Sstevel@tonic-gate # choose a relatively unpredictable tmpfile sequence number 3226*0Sstevel@tonic-gate my $seqno = unpack("%16C*",join('',localtime,values %ENV)); 3227*0Sstevel@tonic-gate for (my $cnt=10;$cnt>0;$cnt--) { 3228*0Sstevel@tonic-gate next unless $tmpfile = new CGITempFile($seqno); 3229*0Sstevel@tonic-gate $tmp = $tmpfile->as_string; 3230*0Sstevel@tonic-gate last if defined($filehandle = Fh->new($filename,$tmp,$PRIVATE_TEMPFILES)); 3231*0Sstevel@tonic-gate $seqno += int rand(100); 3232*0Sstevel@tonic-gate } 3233*0Sstevel@tonic-gate die "CGI open of tmpfile: $!\n" unless defined $filehandle; 3234*0Sstevel@tonic-gate $CGI::DefaultClass->binmode($filehandle) if $CGI::needs_binmode 3235*0Sstevel@tonic-gate && defined fileno($filehandle); 3236*0Sstevel@tonic-gate 3237*0Sstevel@tonic-gate # if this is an multipart/mixed attachment, save the header 3238*0Sstevel@tonic-gate # together with the body for later parsing with an external 3239*0Sstevel@tonic-gate # MIME parser module 3240*0Sstevel@tonic-gate if ( $multipart ) { 3241*0Sstevel@tonic-gate foreach ( keys %header ) { 3242*0Sstevel@tonic-gate print $filehandle "$_: $header{$_}${CRLF}"; 3243*0Sstevel@tonic-gate } 3244*0Sstevel@tonic-gate print $filehandle "${CRLF}"; 3245*0Sstevel@tonic-gate } 3246*0Sstevel@tonic-gate 3247*0Sstevel@tonic-gate my ($data); 3248*0Sstevel@tonic-gate local($\) = ''; 3249*0Sstevel@tonic-gate my $totalbytes; 3250*0Sstevel@tonic-gate while (defined($data = $buffer->read)) { 3251*0Sstevel@tonic-gate if (defined $self->{'.upload_hook'}) 3252*0Sstevel@tonic-gate { 3253*0Sstevel@tonic-gate $totalbytes += length($data); 3254*0Sstevel@tonic-gate &{$self->{'.upload_hook'}}($filename ,$data, $totalbytes, $self->{'.upload_data'}); 3255*0Sstevel@tonic-gate } 3256*0Sstevel@tonic-gate print $filehandle $data; 3257*0Sstevel@tonic-gate } 3258*0Sstevel@tonic-gate 3259*0Sstevel@tonic-gate # back up to beginning of file 3260*0Sstevel@tonic-gate seek($filehandle,0,0); 3261*0Sstevel@tonic-gate 3262*0Sstevel@tonic-gate ## Close the filehandle if requested this allows a multipart MIME 3263*0Sstevel@tonic-gate ## upload to contain many files, and we won't die due to too many 3264*0Sstevel@tonic-gate ## open file handles. The user can access the files using the hash 3265*0Sstevel@tonic-gate ## below. 3266*0Sstevel@tonic-gate close $filehandle if $CLOSE_UPLOAD_FILES; 3267*0Sstevel@tonic-gate $CGI::DefaultClass->binmode($filehandle) if $CGI::needs_binmode; 3268*0Sstevel@tonic-gate 3269*0Sstevel@tonic-gate # Save some information about the uploaded file where we can get 3270*0Sstevel@tonic-gate # at it later. 3271*0Sstevel@tonic-gate $self->{'.tmpfiles'}->{fileno($filehandle)}= { 3272*0Sstevel@tonic-gate hndl => $filehandle, 3273*0Sstevel@tonic-gate name => $tmpfile, 3274*0Sstevel@tonic-gate info => {%header}, 3275*0Sstevel@tonic-gate }; 3276*0Sstevel@tonic-gate push(@{$self->{$param}},$filehandle); 3277*0Sstevel@tonic-gate } 3278*0Sstevel@tonic-gate } 3279*0Sstevel@tonic-gate} 3280*0Sstevel@tonic-gateEND_OF_FUNC 3281*0Sstevel@tonic-gate 3282*0Sstevel@tonic-gate'upload' =><<'END_OF_FUNC', 3283*0Sstevel@tonic-gatesub upload { 3284*0Sstevel@tonic-gate my($self,$param_name) = self_or_default(@_); 3285*0Sstevel@tonic-gate my @param = grep(ref && fileno($_), $self->param($param_name)); 3286*0Sstevel@tonic-gate return unless @param; 3287*0Sstevel@tonic-gate return wantarray ? @param : $param[0]; 3288*0Sstevel@tonic-gate} 3289*0Sstevel@tonic-gateEND_OF_FUNC 3290*0Sstevel@tonic-gate 3291*0Sstevel@tonic-gate'tmpFileName' => <<'END_OF_FUNC', 3292*0Sstevel@tonic-gatesub tmpFileName { 3293*0Sstevel@tonic-gate my($self,$filename) = self_or_default(@_); 3294*0Sstevel@tonic-gate return $self->{'.tmpfiles'}->{fileno($filename)}->{name} ? 3295*0Sstevel@tonic-gate $self->{'.tmpfiles'}->{fileno($filename)}->{name}->as_string 3296*0Sstevel@tonic-gate : ''; 3297*0Sstevel@tonic-gate} 3298*0Sstevel@tonic-gateEND_OF_FUNC 3299*0Sstevel@tonic-gate 3300*0Sstevel@tonic-gate'uploadInfo' => <<'END_OF_FUNC', 3301*0Sstevel@tonic-gatesub uploadInfo { 3302*0Sstevel@tonic-gate my($self,$filename) = self_or_default(@_); 3303*0Sstevel@tonic-gate return $self->{'.tmpfiles'}->{fileno($filename)}->{info}; 3304*0Sstevel@tonic-gate} 3305*0Sstevel@tonic-gateEND_OF_FUNC 3306*0Sstevel@tonic-gate 3307*0Sstevel@tonic-gate# internal routine, don't use 3308*0Sstevel@tonic-gate'_set_values_and_labels' => <<'END_OF_FUNC', 3309*0Sstevel@tonic-gatesub _set_values_and_labels { 3310*0Sstevel@tonic-gate my $self = shift; 3311*0Sstevel@tonic-gate my ($v,$l,$n) = @_; 3312*0Sstevel@tonic-gate $$l = $v if ref($v) eq 'HASH' && !ref($$l); 3313*0Sstevel@tonic-gate return $self->param($n) if !defined($v); 3314*0Sstevel@tonic-gate return $v if !ref($v); 3315*0Sstevel@tonic-gate return ref($v) eq 'HASH' ? keys %$v : @$v; 3316*0Sstevel@tonic-gate} 3317*0Sstevel@tonic-gateEND_OF_FUNC 3318*0Sstevel@tonic-gate 3319*0Sstevel@tonic-gate# internal routine, don't use 3320*0Sstevel@tonic-gate'_set_attributes' => <<'END_OF_FUNC', 3321*0Sstevel@tonic-gatesub _set_attributes { 3322*0Sstevel@tonic-gate my $self = shift; 3323*0Sstevel@tonic-gate my($element, $attributes) = @_; 3324*0Sstevel@tonic-gate return '' unless defined($attributes->{$element}); 3325*0Sstevel@tonic-gate $attribs = ' '; 3326*0Sstevel@tonic-gate foreach my $attrib (keys %{$attributes->{$element}}) { 3327*0Sstevel@tonic-gate $attrib =~ s/^-//; 3328*0Sstevel@tonic-gate $attribs .= "@{[lc($attrib)]}=\"$attributes->{$element}{$attrib}\" "; 3329*0Sstevel@tonic-gate } 3330*0Sstevel@tonic-gate $attribs =~ s/ $//; 3331*0Sstevel@tonic-gate return $attribs; 3332*0Sstevel@tonic-gate} 3333*0Sstevel@tonic-gateEND_OF_FUNC 3334*0Sstevel@tonic-gate 3335*0Sstevel@tonic-gate'_compile_all' => <<'END_OF_FUNC', 3336*0Sstevel@tonic-gatesub _compile_all { 3337*0Sstevel@tonic-gate foreach (@_) { 3338*0Sstevel@tonic-gate next if defined(&$_); 3339*0Sstevel@tonic-gate $AUTOLOAD = "CGI::$_"; 3340*0Sstevel@tonic-gate _compile(); 3341*0Sstevel@tonic-gate } 3342*0Sstevel@tonic-gate} 3343*0Sstevel@tonic-gateEND_OF_FUNC 3344*0Sstevel@tonic-gate 3345*0Sstevel@tonic-gate); 3346*0Sstevel@tonic-gateEND_OF_AUTOLOAD 3347*0Sstevel@tonic-gate; 3348*0Sstevel@tonic-gate 3349*0Sstevel@tonic-gate######################################################### 3350*0Sstevel@tonic-gate# Globals and stubs for other packages that we use. 3351*0Sstevel@tonic-gate######################################################### 3352*0Sstevel@tonic-gate 3353*0Sstevel@tonic-gate################### Fh -- lightweight filehandle ############### 3354*0Sstevel@tonic-gatepackage Fh; 3355*0Sstevel@tonic-gateuse overload 3356*0Sstevel@tonic-gate '""' => \&asString, 3357*0Sstevel@tonic-gate 'cmp' => \&compare, 3358*0Sstevel@tonic-gate 'fallback'=>1; 3359*0Sstevel@tonic-gate 3360*0Sstevel@tonic-gate$FH='fh00000'; 3361*0Sstevel@tonic-gate 3362*0Sstevel@tonic-gate*Fh::AUTOLOAD = \&CGI::AUTOLOAD; 3363*0Sstevel@tonic-gate 3364*0Sstevel@tonic-gate$AUTOLOADED_ROUTINES = ''; # prevent -w error 3365*0Sstevel@tonic-gate$AUTOLOADED_ROUTINES=<<'END_OF_AUTOLOAD'; 3366*0Sstevel@tonic-gate%SUBS = ( 3367*0Sstevel@tonic-gate'asString' => <<'END_OF_FUNC', 3368*0Sstevel@tonic-gatesub asString { 3369*0Sstevel@tonic-gate my $self = shift; 3370*0Sstevel@tonic-gate # get rid of package name 3371*0Sstevel@tonic-gate (my $i = $$self) =~ s/^\*(\w+::fh\d{5})+//; 3372*0Sstevel@tonic-gate $i =~ s/%(..)/ chr(hex($1)) /eg; 3373*0Sstevel@tonic-gate return $i.$CGI::TAINTED; 3374*0Sstevel@tonic-gate# BEGIN DEAD CODE 3375*0Sstevel@tonic-gate# This was an extremely clever patch that allowed "use strict refs". 3376*0Sstevel@tonic-gate# Unfortunately it relied on another bug that caused leaky file descriptors. 3377*0Sstevel@tonic-gate# The underlying bug has been fixed, so this no longer works. However 3378*0Sstevel@tonic-gate# "strict refs" still works for some reason. 3379*0Sstevel@tonic-gate# my $self = shift; 3380*0Sstevel@tonic-gate# return ${*{$self}{SCALAR}}; 3381*0Sstevel@tonic-gate# END DEAD CODE 3382*0Sstevel@tonic-gate} 3383*0Sstevel@tonic-gateEND_OF_FUNC 3384*0Sstevel@tonic-gate 3385*0Sstevel@tonic-gate'compare' => <<'END_OF_FUNC', 3386*0Sstevel@tonic-gatesub compare { 3387*0Sstevel@tonic-gate my $self = shift; 3388*0Sstevel@tonic-gate my $value = shift; 3389*0Sstevel@tonic-gate return "$self" cmp $value; 3390*0Sstevel@tonic-gate} 3391*0Sstevel@tonic-gateEND_OF_FUNC 3392*0Sstevel@tonic-gate 3393*0Sstevel@tonic-gate'new' => <<'END_OF_FUNC', 3394*0Sstevel@tonic-gatesub new { 3395*0Sstevel@tonic-gate my($pack,$name,$file,$delete) = @_; 3396*0Sstevel@tonic-gate _setup_symbols(@SAVED_SYMBOLS) if @SAVED_SYMBOLS; 3397*0Sstevel@tonic-gate require Fcntl unless defined &Fcntl::O_RDWR; 3398*0Sstevel@tonic-gate (my $safename = $name) =~ s/([':%])/ sprintf '%%%02X', ord $1 /eg; 3399*0Sstevel@tonic-gate my $fv = ++$FH . $safename; 3400*0Sstevel@tonic-gate my $ref = \*{"Fh::$fv"}; 3401*0Sstevel@tonic-gate $file =~ m!^([a-zA-Z0-9_ \'\":/.\$\\-]+)$! || return; 3402*0Sstevel@tonic-gate my $safe = $1; 3403*0Sstevel@tonic-gate sysopen($ref,$safe,Fcntl::O_RDWR()|Fcntl::O_CREAT()|Fcntl::O_EXCL(),0600) || return; 3404*0Sstevel@tonic-gate unlink($safe) if $delete; 3405*0Sstevel@tonic-gate CORE::delete $Fh::{$fv}; 3406*0Sstevel@tonic-gate return bless $ref,$pack; 3407*0Sstevel@tonic-gate} 3408*0Sstevel@tonic-gateEND_OF_FUNC 3409*0Sstevel@tonic-gate 3410*0Sstevel@tonic-gate'DESTROY' => <<'END_OF_FUNC', 3411*0Sstevel@tonic-gatesub DESTROY { 3412*0Sstevel@tonic-gate my $self = shift; 3413*0Sstevel@tonic-gate close $self; 3414*0Sstevel@tonic-gate} 3415*0Sstevel@tonic-gateEND_OF_FUNC 3416*0Sstevel@tonic-gate 3417*0Sstevel@tonic-gate); 3418*0Sstevel@tonic-gateEND_OF_AUTOLOAD 3419*0Sstevel@tonic-gate 3420*0Sstevel@tonic-gate######################## MultipartBuffer #################### 3421*0Sstevel@tonic-gatepackage MultipartBuffer; 3422*0Sstevel@tonic-gate 3423*0Sstevel@tonic-gateuse constant DEBUG => 0; 3424*0Sstevel@tonic-gate 3425*0Sstevel@tonic-gate# how many bytes to read at a time. We use 3426*0Sstevel@tonic-gate# a 4K buffer by default. 3427*0Sstevel@tonic-gate$INITIAL_FILLUNIT = 1024 * 4; 3428*0Sstevel@tonic-gate$TIMEOUT = 240*60; # 4 hour timeout for big files 3429*0Sstevel@tonic-gate$SPIN_LOOP_MAX = 2000; # bug fix for some Netscape servers 3430*0Sstevel@tonic-gate$CRLF=$CGI::CRLF; 3431*0Sstevel@tonic-gate 3432*0Sstevel@tonic-gate#reuse the autoload function 3433*0Sstevel@tonic-gate*MultipartBuffer::AUTOLOAD = \&CGI::AUTOLOAD; 3434*0Sstevel@tonic-gate 3435*0Sstevel@tonic-gate# avoid autoloader warnings 3436*0Sstevel@tonic-gatesub DESTROY {} 3437*0Sstevel@tonic-gate 3438*0Sstevel@tonic-gate############################################################################### 3439*0Sstevel@tonic-gate################# THESE FUNCTIONS ARE AUTOLOADED ON DEMAND #################### 3440*0Sstevel@tonic-gate############################################################################### 3441*0Sstevel@tonic-gate$AUTOLOADED_ROUTINES = ''; # prevent -w error 3442*0Sstevel@tonic-gate$AUTOLOADED_ROUTINES=<<'END_OF_AUTOLOAD'; 3443*0Sstevel@tonic-gate%SUBS = ( 3444*0Sstevel@tonic-gate 3445*0Sstevel@tonic-gate'new' => <<'END_OF_FUNC', 3446*0Sstevel@tonic-gatesub new { 3447*0Sstevel@tonic-gate my($package,$interface,$boundary,$length) = @_; 3448*0Sstevel@tonic-gate $FILLUNIT = $INITIAL_FILLUNIT; 3449*0Sstevel@tonic-gate $CGI::DefaultClass->binmode($IN); # if $CGI::needs_binmode; # just do it always 3450*0Sstevel@tonic-gate 3451*0Sstevel@tonic-gate # If the user types garbage into the file upload field, 3452*0Sstevel@tonic-gate # then Netscape passes NOTHING to the server (not good). 3453*0Sstevel@tonic-gate # We may hang on this read in that case. So we implement 3454*0Sstevel@tonic-gate # a read timeout. If nothing is ready to read 3455*0Sstevel@tonic-gate # by then, we return. 3456*0Sstevel@tonic-gate 3457*0Sstevel@tonic-gate # Netscape seems to be a little bit unreliable 3458*0Sstevel@tonic-gate # about providing boundary strings. 3459*0Sstevel@tonic-gate my $boundary_read = 0; 3460*0Sstevel@tonic-gate if ($boundary) { 3461*0Sstevel@tonic-gate 3462*0Sstevel@tonic-gate # Under the MIME spec, the boundary consists of the 3463*0Sstevel@tonic-gate # characters "--" PLUS the Boundary string 3464*0Sstevel@tonic-gate 3465*0Sstevel@tonic-gate # BUG: IE 3.01 on the Macintosh uses just the boundary -- not 3466*0Sstevel@tonic-gate # the two extra hyphens. We do a special case here on the user-agent!!!! 3467*0Sstevel@tonic-gate $boundary = "--$boundary" unless CGI::user_agent('MSIE\s+3\.0[12];\s*Mac|DreamPassport'); 3468*0Sstevel@tonic-gate 3469*0Sstevel@tonic-gate } else { # otherwise we find it ourselves 3470*0Sstevel@tonic-gate my($old); 3471*0Sstevel@tonic-gate ($old,$/) = ($/,$CRLF); # read a CRLF-delimited line 3472*0Sstevel@tonic-gate $boundary = <STDIN>; # BUG: This won't work correctly under mod_perl 3473*0Sstevel@tonic-gate $length -= length($boundary); 3474*0Sstevel@tonic-gate chomp($boundary); # remove the CRLF 3475*0Sstevel@tonic-gate $/ = $old; # restore old line separator 3476*0Sstevel@tonic-gate $boundary_read++; 3477*0Sstevel@tonic-gate } 3478*0Sstevel@tonic-gate 3479*0Sstevel@tonic-gate my $self = {LENGTH=>$length, 3480*0Sstevel@tonic-gate BOUNDARY=>$boundary, 3481*0Sstevel@tonic-gate INTERFACE=>$interface, 3482*0Sstevel@tonic-gate BUFFER=>'', 3483*0Sstevel@tonic-gate }; 3484*0Sstevel@tonic-gate 3485*0Sstevel@tonic-gate $FILLUNIT = length($boundary) 3486*0Sstevel@tonic-gate if length($boundary) > $FILLUNIT; 3487*0Sstevel@tonic-gate 3488*0Sstevel@tonic-gate my $retval = bless $self,ref $package || $package; 3489*0Sstevel@tonic-gate 3490*0Sstevel@tonic-gate # Read the preamble and the topmost (boundary) line plus the CRLF. 3491*0Sstevel@tonic-gate unless ($boundary_read) { 3492*0Sstevel@tonic-gate while ($self->read(0)) { } 3493*0Sstevel@tonic-gate } 3494*0Sstevel@tonic-gate die "Malformed multipart POST: data truncated\n" if $self->eof; 3495*0Sstevel@tonic-gate 3496*0Sstevel@tonic-gate return $retval; 3497*0Sstevel@tonic-gate} 3498*0Sstevel@tonic-gateEND_OF_FUNC 3499*0Sstevel@tonic-gate 3500*0Sstevel@tonic-gate'readHeader' => <<'END_OF_FUNC', 3501*0Sstevel@tonic-gatesub readHeader { 3502*0Sstevel@tonic-gate my($self) = @_; 3503*0Sstevel@tonic-gate my($end); 3504*0Sstevel@tonic-gate my($ok) = 0; 3505*0Sstevel@tonic-gate my($bad) = 0; 3506*0Sstevel@tonic-gate 3507*0Sstevel@tonic-gate local($CRLF) = "\015\012" if $CGI::OS eq 'VMS' || $CGI::EBCDIC; 3508*0Sstevel@tonic-gate 3509*0Sstevel@tonic-gate do { 3510*0Sstevel@tonic-gate $self->fillBuffer($FILLUNIT); 3511*0Sstevel@tonic-gate $ok++ if ($end = index($self->{BUFFER},"${CRLF}${CRLF}")) >= 0; 3512*0Sstevel@tonic-gate $ok++ if $self->{BUFFER} eq ''; 3513*0Sstevel@tonic-gate $bad++ if !$ok && $self->{LENGTH} <= 0; 3514*0Sstevel@tonic-gate # this was a bad idea 3515*0Sstevel@tonic-gate # $FILLUNIT *= 2 if length($self->{BUFFER}) >= $FILLUNIT; 3516*0Sstevel@tonic-gate } until $ok || $bad; 3517*0Sstevel@tonic-gate return () if $bad; 3518*0Sstevel@tonic-gate 3519*0Sstevel@tonic-gate #EBCDIC NOTE: translate header into EBCDIC, but watch out for continuation lines! 3520*0Sstevel@tonic-gate 3521*0Sstevel@tonic-gate my($header) = substr($self->{BUFFER},0,$end+2); 3522*0Sstevel@tonic-gate substr($self->{BUFFER},0,$end+4) = ''; 3523*0Sstevel@tonic-gate my %return; 3524*0Sstevel@tonic-gate 3525*0Sstevel@tonic-gate if ($CGI::EBCDIC) { 3526*0Sstevel@tonic-gate warn "untranslated header=$header\n" if DEBUG; 3527*0Sstevel@tonic-gate $header = CGI::Util::ascii2ebcdic($header); 3528*0Sstevel@tonic-gate warn "translated header=$header\n" if DEBUG; 3529*0Sstevel@tonic-gate } 3530*0Sstevel@tonic-gate 3531*0Sstevel@tonic-gate # See RFC 2045 Appendix A and RFC 822 sections 3.4.8 3532*0Sstevel@tonic-gate # (Folding Long Header Fields), 3.4.3 (Comments) 3533*0Sstevel@tonic-gate # and 3.4.5 (Quoted-Strings). 3534*0Sstevel@tonic-gate 3535*0Sstevel@tonic-gate my $token = '[-\w!\#$%&\'*+.^_\`|{}~]'; 3536*0Sstevel@tonic-gate $header=~s/$CRLF\s+/ /og; # merge continuation lines 3537*0Sstevel@tonic-gate 3538*0Sstevel@tonic-gate while ($header=~/($token+):\s+([^$CRLF]*)/mgox) { 3539*0Sstevel@tonic-gate my ($field_name,$field_value) = ($1,$2); 3540*0Sstevel@tonic-gate $field_name =~ s/\b(\w)/uc($1)/eg; #canonicalize 3541*0Sstevel@tonic-gate $return{$field_name}=$field_value; 3542*0Sstevel@tonic-gate } 3543*0Sstevel@tonic-gate return %return; 3544*0Sstevel@tonic-gate} 3545*0Sstevel@tonic-gateEND_OF_FUNC 3546*0Sstevel@tonic-gate 3547*0Sstevel@tonic-gate# This reads and returns the body as a single scalar value. 3548*0Sstevel@tonic-gate'readBody' => <<'END_OF_FUNC', 3549*0Sstevel@tonic-gatesub readBody { 3550*0Sstevel@tonic-gate my($self) = @_; 3551*0Sstevel@tonic-gate my($data); 3552*0Sstevel@tonic-gate my($returnval)=''; 3553*0Sstevel@tonic-gate 3554*0Sstevel@tonic-gate #EBCDIC NOTE: want to translate returnval into EBCDIC HERE 3555*0Sstevel@tonic-gate 3556*0Sstevel@tonic-gate while (defined($data = $self->read)) { 3557*0Sstevel@tonic-gate $returnval .= $data; 3558*0Sstevel@tonic-gate } 3559*0Sstevel@tonic-gate 3560*0Sstevel@tonic-gate if ($CGI::EBCDIC) { 3561*0Sstevel@tonic-gate warn "untranslated body=$returnval\n" if DEBUG; 3562*0Sstevel@tonic-gate $returnval = CGI::Util::ascii2ebcdic($returnval); 3563*0Sstevel@tonic-gate warn "translated body=$returnval\n" if DEBUG; 3564*0Sstevel@tonic-gate } 3565*0Sstevel@tonic-gate return $returnval; 3566*0Sstevel@tonic-gate} 3567*0Sstevel@tonic-gateEND_OF_FUNC 3568*0Sstevel@tonic-gate 3569*0Sstevel@tonic-gate# This will read $bytes or until the boundary is hit, whichever happens 3570*0Sstevel@tonic-gate# first. After the boundary is hit, we return undef. The next read will 3571*0Sstevel@tonic-gate# skip over the boundary and begin reading again; 3572*0Sstevel@tonic-gate'read' => <<'END_OF_FUNC', 3573*0Sstevel@tonic-gatesub read { 3574*0Sstevel@tonic-gate my($self,$bytes) = @_; 3575*0Sstevel@tonic-gate 3576*0Sstevel@tonic-gate # default number of bytes to read 3577*0Sstevel@tonic-gate $bytes = $bytes || $FILLUNIT; 3578*0Sstevel@tonic-gate 3579*0Sstevel@tonic-gate # Fill up our internal buffer in such a way that the boundary 3580*0Sstevel@tonic-gate # is never split between reads. 3581*0Sstevel@tonic-gate $self->fillBuffer($bytes); 3582*0Sstevel@tonic-gate 3583*0Sstevel@tonic-gate my $boundary_start = $CGI::EBCDIC ? CGI::Util::ebcdic2ascii($self->{BOUNDARY}) : $self->{BOUNDARY}; 3584*0Sstevel@tonic-gate my $boundary_end = $CGI::EBCDIC ? CGI::Util::ebcdic2ascii($self->{BOUNDARY}.'--') : $self->{BOUNDARY}.'--'; 3585*0Sstevel@tonic-gate 3586*0Sstevel@tonic-gate # Find the boundary in the buffer (it may not be there). 3587*0Sstevel@tonic-gate my $start = index($self->{BUFFER},$boundary_start); 3588*0Sstevel@tonic-gate 3589*0Sstevel@tonic-gate warn "boundary=$self->{BOUNDARY} length=$self->{LENGTH} start=$start\n" if DEBUG; 3590*0Sstevel@tonic-gate # protect against malformed multipart POST operations 3591*0Sstevel@tonic-gate die "Malformed multipart POST\n" unless ($start >= 0) || ($self->{LENGTH} > 0); 3592*0Sstevel@tonic-gate 3593*0Sstevel@tonic-gate 3594*0Sstevel@tonic-gate #EBCDIC NOTE: want to translate boundary search into ASCII here. 3595*0Sstevel@tonic-gate 3596*0Sstevel@tonic-gate # If the boundary begins the data, then skip past it 3597*0Sstevel@tonic-gate # and return undef. 3598*0Sstevel@tonic-gate if ($start == 0) { 3599*0Sstevel@tonic-gate 3600*0Sstevel@tonic-gate # clear us out completely if we've hit the last boundary. 3601*0Sstevel@tonic-gate if (index($self->{BUFFER},$boundary_end)==0) { 3602*0Sstevel@tonic-gate $self->{BUFFER}=''; 3603*0Sstevel@tonic-gate $self->{LENGTH}=0; 3604*0Sstevel@tonic-gate return undef; 3605*0Sstevel@tonic-gate } 3606*0Sstevel@tonic-gate 3607*0Sstevel@tonic-gate # just remove the boundary. 3608*0Sstevel@tonic-gate substr($self->{BUFFER},0,length($boundary_start))=''; 3609*0Sstevel@tonic-gate $self->{BUFFER} =~ s/^\012\015?//; 3610*0Sstevel@tonic-gate return undef; 3611*0Sstevel@tonic-gate } 3612*0Sstevel@tonic-gate 3613*0Sstevel@tonic-gate my $bytesToReturn; 3614*0Sstevel@tonic-gate if ($start > 0) { # read up to the boundary 3615*0Sstevel@tonic-gate $bytesToReturn = $start-2 > $bytes ? $bytes : $start; 3616*0Sstevel@tonic-gate } else { # read the requested number of bytes 3617*0Sstevel@tonic-gate # leave enough bytes in the buffer to allow us to read 3618*0Sstevel@tonic-gate # the boundary. Thanks to Kevin Hendrick for finding 3619*0Sstevel@tonic-gate # this one. 3620*0Sstevel@tonic-gate $bytesToReturn = $bytes - (length($boundary_start)+1); 3621*0Sstevel@tonic-gate } 3622*0Sstevel@tonic-gate 3623*0Sstevel@tonic-gate my $returnval=substr($self->{BUFFER},0,$bytesToReturn); 3624*0Sstevel@tonic-gate substr($self->{BUFFER},0,$bytesToReturn)=''; 3625*0Sstevel@tonic-gate 3626*0Sstevel@tonic-gate # If we hit the boundary, remove the CRLF from the end. 3627*0Sstevel@tonic-gate return ($bytesToReturn==$start) 3628*0Sstevel@tonic-gate ? substr($returnval,0,-2) : $returnval; 3629*0Sstevel@tonic-gate} 3630*0Sstevel@tonic-gateEND_OF_FUNC 3631*0Sstevel@tonic-gate 3632*0Sstevel@tonic-gate 3633*0Sstevel@tonic-gate# This fills up our internal buffer in such a way that the 3634*0Sstevel@tonic-gate# boundary is never split between reads 3635*0Sstevel@tonic-gate'fillBuffer' => <<'END_OF_FUNC', 3636*0Sstevel@tonic-gatesub fillBuffer { 3637*0Sstevel@tonic-gate my($self,$bytes) = @_; 3638*0Sstevel@tonic-gate return unless $self->{LENGTH}; 3639*0Sstevel@tonic-gate 3640*0Sstevel@tonic-gate my($boundaryLength) = length($self->{BOUNDARY}); 3641*0Sstevel@tonic-gate my($bufferLength) = length($self->{BUFFER}); 3642*0Sstevel@tonic-gate my($bytesToRead) = $bytes - $bufferLength + $boundaryLength + 2; 3643*0Sstevel@tonic-gate $bytesToRead = $self->{LENGTH} if $self->{LENGTH} < $bytesToRead; 3644*0Sstevel@tonic-gate 3645*0Sstevel@tonic-gate # Try to read some data. We may hang here if the browser is screwed up. 3646*0Sstevel@tonic-gate my $bytesRead = $self->{INTERFACE}->read_from_client(\$self->{BUFFER}, 3647*0Sstevel@tonic-gate $bytesToRead, 3648*0Sstevel@tonic-gate $bufferLength); 3649*0Sstevel@tonic-gate warn "bytesToRead=$bytesToRead, bufferLength=$bufferLength, buffer=$self->{BUFFER}\n" if DEBUG; 3650*0Sstevel@tonic-gate $self->{BUFFER} = '' unless defined $self->{BUFFER}; 3651*0Sstevel@tonic-gate 3652*0Sstevel@tonic-gate # An apparent bug in the Apache server causes the read() 3653*0Sstevel@tonic-gate # to return zero bytes repeatedly without blocking if the 3654*0Sstevel@tonic-gate # remote user aborts during a file transfer. I don't know how 3655*0Sstevel@tonic-gate # they manage this, but the workaround is to abort if we get 3656*0Sstevel@tonic-gate # more than SPIN_LOOP_MAX consecutive zero reads. 3657*0Sstevel@tonic-gate if ($bytesRead == 0) { 3658*0Sstevel@tonic-gate die "CGI.pm: Server closed socket during multipart read (client aborted?).\n" 3659*0Sstevel@tonic-gate if ($self->{ZERO_LOOP_COUNTER}++ >= $SPIN_LOOP_MAX); 3660*0Sstevel@tonic-gate } else { 3661*0Sstevel@tonic-gate $self->{ZERO_LOOP_COUNTER}=0; 3662*0Sstevel@tonic-gate } 3663*0Sstevel@tonic-gate 3664*0Sstevel@tonic-gate $self->{LENGTH} -= $bytesRead; 3665*0Sstevel@tonic-gate} 3666*0Sstevel@tonic-gateEND_OF_FUNC 3667*0Sstevel@tonic-gate 3668*0Sstevel@tonic-gate 3669*0Sstevel@tonic-gate# Return true when we've finished reading 3670*0Sstevel@tonic-gate'eof' => <<'END_OF_FUNC' 3671*0Sstevel@tonic-gatesub eof { 3672*0Sstevel@tonic-gate my($self) = @_; 3673*0Sstevel@tonic-gate return 1 if (length($self->{BUFFER}) == 0) 3674*0Sstevel@tonic-gate && ($self->{LENGTH} <= 0); 3675*0Sstevel@tonic-gate undef; 3676*0Sstevel@tonic-gate} 3677*0Sstevel@tonic-gateEND_OF_FUNC 3678*0Sstevel@tonic-gate 3679*0Sstevel@tonic-gate); 3680*0Sstevel@tonic-gateEND_OF_AUTOLOAD 3681*0Sstevel@tonic-gate 3682*0Sstevel@tonic-gate#################################################################################### 3683*0Sstevel@tonic-gate################################## TEMPORARY FILES ################################# 3684*0Sstevel@tonic-gate#################################################################################### 3685*0Sstevel@tonic-gatepackage CGITempFile; 3686*0Sstevel@tonic-gate 3687*0Sstevel@tonic-gatesub find_tempdir { 3688*0Sstevel@tonic-gate undef $TMPDIRECTORY; 3689*0Sstevel@tonic-gate $SL = $CGI::SL; 3690*0Sstevel@tonic-gate $MAC = $CGI::OS eq 'MACINTOSH'; 3691*0Sstevel@tonic-gate my ($vol) = $MAC ? MacPerl::Volumes() =~ /:(.*)/ : ""; 3692*0Sstevel@tonic-gate unless ($TMPDIRECTORY) { 3693*0Sstevel@tonic-gate @TEMP=("${SL}usr${SL}tmp","${SL}var${SL}tmp", 3694*0Sstevel@tonic-gate "C:${SL}temp","${SL}tmp","${SL}temp", 3695*0Sstevel@tonic-gate "${vol}${SL}Temporary Items", 3696*0Sstevel@tonic-gate "${SL}WWW_ROOT", "${SL}SYS\$SCRATCH", 3697*0Sstevel@tonic-gate "C:${SL}system${SL}temp"); 3698*0Sstevel@tonic-gate unshift(@TEMP,$ENV{'TMPDIR'}) if defined $ENV{'TMPDIR'}; 3699*0Sstevel@tonic-gate 3700*0Sstevel@tonic-gate # this feature was supposed to provide per-user tmpfiles, but 3701*0Sstevel@tonic-gate # it is problematic. 3702*0Sstevel@tonic-gate # unshift(@TEMP,(getpwuid($<))[7].'/tmp') if $CGI::OS eq 'UNIX'; 3703*0Sstevel@tonic-gate # Rob: getpwuid() is unfortunately UNIX specific. On brain dead OS'es this 3704*0Sstevel@tonic-gate # : can generate a 'getpwuid() not implemented' exception, even though 3705*0Sstevel@tonic-gate # : it's never called. Found under DOS/Win with the DJGPP perl port. 3706*0Sstevel@tonic-gate # : Refer to getpwuid() only at run-time if we're fortunate and have UNIX. 3707*0Sstevel@tonic-gate # unshift(@TEMP,(eval {(getpwuid($>))[7]}).'/tmp') if $CGI::OS eq 'UNIX' and $> != 0; 3708*0Sstevel@tonic-gate 3709*0Sstevel@tonic-gate foreach (@TEMP) { 3710*0Sstevel@tonic-gate do {$TMPDIRECTORY = $_; last} if -d $_ && -w _; 3711*0Sstevel@tonic-gate } 3712*0Sstevel@tonic-gate } 3713*0Sstevel@tonic-gate $TMPDIRECTORY = $MAC ? "" : "." unless $TMPDIRECTORY; 3714*0Sstevel@tonic-gate} 3715*0Sstevel@tonic-gate 3716*0Sstevel@tonic-gatefind_tempdir(); 3717*0Sstevel@tonic-gate 3718*0Sstevel@tonic-gate$MAXTRIES = 5000; 3719*0Sstevel@tonic-gate 3720*0Sstevel@tonic-gate# cute feature, but overload implementation broke it 3721*0Sstevel@tonic-gate# %OVERLOAD = ('""'=>'as_string'); 3722*0Sstevel@tonic-gate*CGITempFile::AUTOLOAD = \&CGI::AUTOLOAD; 3723*0Sstevel@tonic-gate 3724*0Sstevel@tonic-gatesub DESTROY { 3725*0Sstevel@tonic-gate my($self) = @_; 3726*0Sstevel@tonic-gate $$self =~ m!^([a-zA-Z0-9_ \'\":/.\$\\-]+)$! || return; 3727*0Sstevel@tonic-gate my $safe = $1; # untaint operation 3728*0Sstevel@tonic-gate unlink $safe; # get rid of the file 3729*0Sstevel@tonic-gate} 3730*0Sstevel@tonic-gate 3731*0Sstevel@tonic-gate############################################################################### 3732*0Sstevel@tonic-gate################# THESE FUNCTIONS ARE AUTOLOADED ON DEMAND #################### 3733*0Sstevel@tonic-gate############################################################################### 3734*0Sstevel@tonic-gate$AUTOLOADED_ROUTINES = ''; # prevent -w error 3735*0Sstevel@tonic-gate$AUTOLOADED_ROUTINES=<<'END_OF_AUTOLOAD'; 3736*0Sstevel@tonic-gate%SUBS = ( 3737*0Sstevel@tonic-gate 3738*0Sstevel@tonic-gate'new' => <<'END_OF_FUNC', 3739*0Sstevel@tonic-gatesub new { 3740*0Sstevel@tonic-gate my($package,$sequence) = @_; 3741*0Sstevel@tonic-gate my $filename; 3742*0Sstevel@tonic-gate find_tempdir() unless -w $TMPDIRECTORY; 3743*0Sstevel@tonic-gate for (my $i = 0; $i < $MAXTRIES; $i++) { 3744*0Sstevel@tonic-gate last if ! -f ($filename = sprintf("${TMPDIRECTORY}${SL}CGItemp%d",$sequence++)); 3745*0Sstevel@tonic-gate } 3746*0Sstevel@tonic-gate # check that it is a more-or-less valid filename 3747*0Sstevel@tonic-gate return unless $filename =~ m!^([a-zA-Z0-9_ \'\":/.\$\\-]+)$!; 3748*0Sstevel@tonic-gate # this used to untaint, now it doesn't 3749*0Sstevel@tonic-gate # $filename = $1; 3750*0Sstevel@tonic-gate return bless \$filename; 3751*0Sstevel@tonic-gate} 3752*0Sstevel@tonic-gateEND_OF_FUNC 3753*0Sstevel@tonic-gate 3754*0Sstevel@tonic-gate'as_string' => <<'END_OF_FUNC' 3755*0Sstevel@tonic-gatesub as_string { 3756*0Sstevel@tonic-gate my($self) = @_; 3757*0Sstevel@tonic-gate return $$self; 3758*0Sstevel@tonic-gate} 3759*0Sstevel@tonic-gateEND_OF_FUNC 3760*0Sstevel@tonic-gate 3761*0Sstevel@tonic-gate); 3762*0Sstevel@tonic-gateEND_OF_AUTOLOAD 3763*0Sstevel@tonic-gate 3764*0Sstevel@tonic-gatepackage CGI; 3765*0Sstevel@tonic-gate 3766*0Sstevel@tonic-gate# We get a whole bunch of warnings about "possibly uninitialized variables" 3767*0Sstevel@tonic-gate# when running with the -w switch. Touch them all once to get rid of the 3768*0Sstevel@tonic-gate# warnings. This is ugly and I hate it. 3769*0Sstevel@tonic-gateif ($^W) { 3770*0Sstevel@tonic-gate $CGI::CGI = ''; 3771*0Sstevel@tonic-gate $CGI::CGI=<<EOF; 3772*0Sstevel@tonic-gate $CGI::VERSION; 3773*0Sstevel@tonic-gate $MultipartBuffer::SPIN_LOOP_MAX; 3774*0Sstevel@tonic-gate $MultipartBuffer::CRLF; 3775*0Sstevel@tonic-gate $MultipartBuffer::TIMEOUT; 3776*0Sstevel@tonic-gate $MultipartBuffer::INITIAL_FILLUNIT; 3777*0Sstevel@tonic-gateEOF 3778*0Sstevel@tonic-gate ; 3779*0Sstevel@tonic-gate} 3780*0Sstevel@tonic-gate 3781*0Sstevel@tonic-gate1; 3782*0Sstevel@tonic-gate 3783*0Sstevel@tonic-gate__END__ 3784*0Sstevel@tonic-gate 3785*0Sstevel@tonic-gate=head1 NAME 3786*0Sstevel@tonic-gate 3787*0Sstevel@tonic-gateCGI - Simple Common Gateway Interface Class 3788*0Sstevel@tonic-gate 3789*0Sstevel@tonic-gate=head1 SYNOPSIS 3790*0Sstevel@tonic-gate 3791*0Sstevel@tonic-gate # CGI script that creates a fill-out form 3792*0Sstevel@tonic-gate # and echoes back its values. 3793*0Sstevel@tonic-gate 3794*0Sstevel@tonic-gate use CGI qw/:standard/; 3795*0Sstevel@tonic-gate print header, 3796*0Sstevel@tonic-gate start_html('A Simple Example'), 3797*0Sstevel@tonic-gate h1('A Simple Example'), 3798*0Sstevel@tonic-gate start_form, 3799*0Sstevel@tonic-gate "What's your name? ",textfield('name'),p, 3800*0Sstevel@tonic-gate "What's the combination?", p, 3801*0Sstevel@tonic-gate checkbox_group(-name=>'words', 3802*0Sstevel@tonic-gate -values=>['eenie','meenie','minie','moe'], 3803*0Sstevel@tonic-gate -defaults=>['eenie','minie']), p, 3804*0Sstevel@tonic-gate "What's your favorite color? ", 3805*0Sstevel@tonic-gate popup_menu(-name=>'color', 3806*0Sstevel@tonic-gate -values=>['red','green','blue','chartreuse']),p, 3807*0Sstevel@tonic-gate submit, 3808*0Sstevel@tonic-gate end_form, 3809*0Sstevel@tonic-gate hr; 3810*0Sstevel@tonic-gate 3811*0Sstevel@tonic-gate if (param()) { 3812*0Sstevel@tonic-gate print "Your name is",em(param('name')),p, 3813*0Sstevel@tonic-gate "The keywords are: ",em(join(", ",param('words'))),p, 3814*0Sstevel@tonic-gate "Your favorite color is ",em(param('color')), 3815*0Sstevel@tonic-gate hr; 3816*0Sstevel@tonic-gate } 3817*0Sstevel@tonic-gate 3818*0Sstevel@tonic-gate=head1 ABSTRACT 3819*0Sstevel@tonic-gate 3820*0Sstevel@tonic-gateThis perl library uses perl5 objects to make it easy to create Web 3821*0Sstevel@tonic-gatefill-out forms and parse their contents. This package defines CGI 3822*0Sstevel@tonic-gateobjects, entities that contain the values of the current query string 3823*0Sstevel@tonic-gateand other state variables. Using a CGI object's methods, you can 3824*0Sstevel@tonic-gateexamine keywords and parameters passed to your script, and create 3825*0Sstevel@tonic-gateforms whose initial values are taken from the current query (thereby 3826*0Sstevel@tonic-gatepreserving state information). The module provides shortcut functions 3827*0Sstevel@tonic-gatethat produce boilerplate HTML, reducing typing and coding errors. It 3828*0Sstevel@tonic-gatealso provides functionality for some of the more advanced features of 3829*0Sstevel@tonic-gateCGI scripting, including support for file uploads, cookies, cascading 3830*0Sstevel@tonic-gatestyle sheets, server push, and frames. 3831*0Sstevel@tonic-gate 3832*0Sstevel@tonic-gateCGI.pm also provides a simple function-oriented programming style for 3833*0Sstevel@tonic-gatethose who don't need its object-oriented features. 3834*0Sstevel@tonic-gate 3835*0Sstevel@tonic-gateThe current version of CGI.pm is available at 3836*0Sstevel@tonic-gate 3837*0Sstevel@tonic-gate http://www.genome.wi.mit.edu/ftp/pub/software/WWW/cgi_docs.html 3838*0Sstevel@tonic-gate ftp://ftp-genome.wi.mit.edu/pub/software/WWW/ 3839*0Sstevel@tonic-gate 3840*0Sstevel@tonic-gate=head1 DESCRIPTION 3841*0Sstevel@tonic-gate 3842*0Sstevel@tonic-gate=head2 PROGRAMMING STYLE 3843*0Sstevel@tonic-gate 3844*0Sstevel@tonic-gateThere are two styles of programming with CGI.pm, an object-oriented 3845*0Sstevel@tonic-gatestyle and a function-oriented style. In the object-oriented style you 3846*0Sstevel@tonic-gatecreate one or more CGI objects and then use object methods to create 3847*0Sstevel@tonic-gatethe various elements of the page. Each CGI object starts out with the 3848*0Sstevel@tonic-gatelist of named parameters that were passed to your CGI script by the 3849*0Sstevel@tonic-gateserver. You can modify the objects, save them to a file or database 3850*0Sstevel@tonic-gateand recreate them. Because each object corresponds to the "state" of 3851*0Sstevel@tonic-gatethe CGI script, and because each object's parameter list is 3852*0Sstevel@tonic-gateindependent of the others, this allows you to save the state of the 3853*0Sstevel@tonic-gatescript and restore it later. 3854*0Sstevel@tonic-gate 3855*0Sstevel@tonic-gateFor example, using the object oriented style, here is how you create 3856*0Sstevel@tonic-gatea simple "Hello World" HTML page: 3857*0Sstevel@tonic-gate 3858*0Sstevel@tonic-gate #!/usr/local/bin/perl -w 3859*0Sstevel@tonic-gate use CGI; # load CGI routines 3860*0Sstevel@tonic-gate $q = new CGI; # create new CGI object 3861*0Sstevel@tonic-gate print $q->header, # create the HTTP header 3862*0Sstevel@tonic-gate $q->start_html('hello world'), # start the HTML 3863*0Sstevel@tonic-gate $q->h1('hello world'), # level 1 header 3864*0Sstevel@tonic-gate $q->end_html; # end the HTML 3865*0Sstevel@tonic-gate 3866*0Sstevel@tonic-gateIn the function-oriented style, there is one default CGI object that 3867*0Sstevel@tonic-gateyou rarely deal with directly. Instead you just call functions to 3868*0Sstevel@tonic-gateretrieve CGI parameters, create HTML tags, manage cookies, and so 3869*0Sstevel@tonic-gateon. This provides you with a cleaner programming interface, but 3870*0Sstevel@tonic-gatelimits you to using one CGI object at a time. The following example 3871*0Sstevel@tonic-gateprints the same page, but uses the function-oriented interface. 3872*0Sstevel@tonic-gateThe main differences are that we now need to import a set of functions 3873*0Sstevel@tonic-gateinto our name space (usually the "standard" functions), and we don't 3874*0Sstevel@tonic-gateneed to create the CGI object. 3875*0Sstevel@tonic-gate 3876*0Sstevel@tonic-gate #!/usr/local/bin/perl 3877*0Sstevel@tonic-gate use CGI qw/:standard/; # load standard CGI routines 3878*0Sstevel@tonic-gate print header, # create the HTTP header 3879*0Sstevel@tonic-gate start_html('hello world'), # start the HTML 3880*0Sstevel@tonic-gate h1('hello world'), # level 1 header 3881*0Sstevel@tonic-gate end_html; # end the HTML 3882*0Sstevel@tonic-gate 3883*0Sstevel@tonic-gateThe examples in this document mainly use the object-oriented style. 3884*0Sstevel@tonic-gateSee HOW TO IMPORT FUNCTIONS for important information on 3885*0Sstevel@tonic-gatefunction-oriented programming in CGI.pm 3886*0Sstevel@tonic-gate 3887*0Sstevel@tonic-gate=head2 CALLING CGI.PM ROUTINES 3888*0Sstevel@tonic-gate 3889*0Sstevel@tonic-gateMost CGI.pm routines accept several arguments, sometimes as many as 20 3890*0Sstevel@tonic-gateoptional ones! To simplify this interface, all routines use a named 3891*0Sstevel@tonic-gateargument calling style that looks like this: 3892*0Sstevel@tonic-gate 3893*0Sstevel@tonic-gate print $q->header(-type=>'image/gif',-expires=>'+3d'); 3894*0Sstevel@tonic-gate 3895*0Sstevel@tonic-gateEach argument name is preceded by a dash. Neither case nor order 3896*0Sstevel@tonic-gatematters in the argument list. -type, -Type, and -TYPE are all 3897*0Sstevel@tonic-gateacceptable. In fact, only the first argument needs to begin with a 3898*0Sstevel@tonic-gatedash. If a dash is present in the first argument, CGI.pm assumes 3899*0Sstevel@tonic-gatedashes for the subsequent ones. 3900*0Sstevel@tonic-gate 3901*0Sstevel@tonic-gateSeveral routines are commonly called with just one argument. In the 3902*0Sstevel@tonic-gatecase of these routines you can provide the single argument without an 3903*0Sstevel@tonic-gateargument name. header() happens to be one of these routines. In this 3904*0Sstevel@tonic-gatecase, the single argument is the document type. 3905*0Sstevel@tonic-gate 3906*0Sstevel@tonic-gate print $q->header('text/html'); 3907*0Sstevel@tonic-gate 3908*0Sstevel@tonic-gateOther such routines are documented below. 3909*0Sstevel@tonic-gate 3910*0Sstevel@tonic-gateSometimes named arguments expect a scalar, sometimes a reference to an 3911*0Sstevel@tonic-gatearray, and sometimes a reference to a hash. Often, you can pass any 3912*0Sstevel@tonic-gatetype of argument and the routine will do whatever is most appropriate. 3913*0Sstevel@tonic-gateFor example, the param() routine is used to set a CGI parameter to a 3914*0Sstevel@tonic-gatesingle or a multi-valued value. The two cases are shown below: 3915*0Sstevel@tonic-gate 3916*0Sstevel@tonic-gate $q->param(-name=>'veggie',-value=>'tomato'); 3917*0Sstevel@tonic-gate $q->param(-name=>'veggie',-value=>['tomato','tomahto','potato','potahto']); 3918*0Sstevel@tonic-gate 3919*0Sstevel@tonic-gateA large number of routines in CGI.pm actually aren't specifically 3920*0Sstevel@tonic-gatedefined in the module, but are generated automatically as needed. 3921*0Sstevel@tonic-gateThese are the "HTML shortcuts," routines that generate HTML tags for 3922*0Sstevel@tonic-gateuse in dynamically-generated pages. HTML tags have both attributes 3923*0Sstevel@tonic-gate(the attribute="value" pairs within the tag itself) and contents (the 3924*0Sstevel@tonic-gatepart between the opening and closing pairs.) To distinguish between 3925*0Sstevel@tonic-gateattributes and contents, CGI.pm uses the convention of passing HTML 3926*0Sstevel@tonic-gateattributes as a hash reference as the first argument, and the 3927*0Sstevel@tonic-gatecontents, if any, as any subsequent arguments. It works out like 3928*0Sstevel@tonic-gatethis: 3929*0Sstevel@tonic-gate 3930*0Sstevel@tonic-gate Code Generated HTML 3931*0Sstevel@tonic-gate ---- -------------- 3932*0Sstevel@tonic-gate h1() <h1> 3933*0Sstevel@tonic-gate h1('some','contents'); <h1>some contents</h1> 3934*0Sstevel@tonic-gate h1({-align=>left}); <h1 align="LEFT"> 3935*0Sstevel@tonic-gate h1({-align=>left},'contents'); <h1 align="LEFT">contents</h1> 3936*0Sstevel@tonic-gate 3937*0Sstevel@tonic-gateHTML tags are described in more detail later. 3938*0Sstevel@tonic-gate 3939*0Sstevel@tonic-gateMany newcomers to CGI.pm are puzzled by the difference between the 3940*0Sstevel@tonic-gatecalling conventions for the HTML shortcuts, which require curly braces 3941*0Sstevel@tonic-gatearound the HTML tag attributes, and the calling conventions for other 3942*0Sstevel@tonic-gateroutines, which manage to generate attributes without the curly 3943*0Sstevel@tonic-gatebrackets. Don't be confused. As a convenience the curly braces are 3944*0Sstevel@tonic-gateoptional in all but the HTML shortcuts. If you like, you can use 3945*0Sstevel@tonic-gatecurly braces when calling any routine that takes named arguments. For 3946*0Sstevel@tonic-gateexample: 3947*0Sstevel@tonic-gate 3948*0Sstevel@tonic-gate print $q->header( {-type=>'image/gif',-expires=>'+3d'} ); 3949*0Sstevel@tonic-gate 3950*0Sstevel@tonic-gateIf you use the B<-w> switch, you will be warned that some CGI.pm argument 3951*0Sstevel@tonic-gatenames conflict with built-in Perl functions. The most frequent of 3952*0Sstevel@tonic-gatethese is the -values argument, used to create multi-valued menus, 3953*0Sstevel@tonic-gateradio button clusters and the like. To get around this warning, you 3954*0Sstevel@tonic-gatehave several choices: 3955*0Sstevel@tonic-gate 3956*0Sstevel@tonic-gate=over 4 3957*0Sstevel@tonic-gate 3958*0Sstevel@tonic-gate=item 1. 3959*0Sstevel@tonic-gate 3960*0Sstevel@tonic-gateUse another name for the argument, if one is available. 3961*0Sstevel@tonic-gateFor example, -value is an alias for -values. 3962*0Sstevel@tonic-gate 3963*0Sstevel@tonic-gate=item 2. 3964*0Sstevel@tonic-gate 3965*0Sstevel@tonic-gateChange the capitalization, e.g. -Values 3966*0Sstevel@tonic-gate 3967*0Sstevel@tonic-gate=item 3. 3968*0Sstevel@tonic-gate 3969*0Sstevel@tonic-gatePut quotes around the argument name, e.g. '-values' 3970*0Sstevel@tonic-gate 3971*0Sstevel@tonic-gate=back 3972*0Sstevel@tonic-gate 3973*0Sstevel@tonic-gateMany routines will do something useful with a named argument that it 3974*0Sstevel@tonic-gatedoesn't recognize. For example, you can produce non-standard HTTP 3975*0Sstevel@tonic-gateheader fields by providing them as named arguments: 3976*0Sstevel@tonic-gate 3977*0Sstevel@tonic-gate print $q->header(-type => 'text/html', 3978*0Sstevel@tonic-gate -cost => 'Three smackers', 3979*0Sstevel@tonic-gate -annoyance_level => 'high', 3980*0Sstevel@tonic-gate -complaints_to => 'bit bucket'); 3981*0Sstevel@tonic-gate 3982*0Sstevel@tonic-gateThis will produce the following nonstandard HTTP header: 3983*0Sstevel@tonic-gate 3984*0Sstevel@tonic-gate HTTP/1.0 200 OK 3985*0Sstevel@tonic-gate Cost: Three smackers 3986*0Sstevel@tonic-gate Annoyance-level: high 3987*0Sstevel@tonic-gate Complaints-to: bit bucket 3988*0Sstevel@tonic-gate Content-type: text/html 3989*0Sstevel@tonic-gate 3990*0Sstevel@tonic-gateNotice the way that underscores are translated automatically into 3991*0Sstevel@tonic-gatehyphens. HTML-generating routines perform a different type of 3992*0Sstevel@tonic-gatetranslation. 3993*0Sstevel@tonic-gate 3994*0Sstevel@tonic-gateThis feature allows you to keep up with the rapidly changing HTTP and 3995*0Sstevel@tonic-gateHTML "standards". 3996*0Sstevel@tonic-gate 3997*0Sstevel@tonic-gate=head2 CREATING A NEW QUERY OBJECT (OBJECT-ORIENTED STYLE): 3998*0Sstevel@tonic-gate 3999*0Sstevel@tonic-gate $query = new CGI; 4000*0Sstevel@tonic-gate 4001*0Sstevel@tonic-gateThis will parse the input (from both POST and GET methods) and store 4002*0Sstevel@tonic-gateit into a perl5 object called $query. 4003*0Sstevel@tonic-gate 4004*0Sstevel@tonic-gate=head2 CREATING A NEW QUERY OBJECT FROM AN INPUT FILE 4005*0Sstevel@tonic-gate 4006*0Sstevel@tonic-gate $query = new CGI(INPUTFILE); 4007*0Sstevel@tonic-gate 4008*0Sstevel@tonic-gateIf you provide a file handle to the new() method, it will read 4009*0Sstevel@tonic-gateparameters from the file (or STDIN, or whatever). The file can be in 4010*0Sstevel@tonic-gateany of the forms describing below under debugging (i.e. a series of 4011*0Sstevel@tonic-gatenewline delimited TAG=VALUE pairs will work). Conveniently, this type 4012*0Sstevel@tonic-gateof file is created by the save() method (see below). Multiple records 4013*0Sstevel@tonic-gatecan be saved and restored. 4014*0Sstevel@tonic-gate 4015*0Sstevel@tonic-gatePerl purists will be pleased to know that this syntax accepts 4016*0Sstevel@tonic-gatereferences to file handles, or even references to filehandle globs, 4017*0Sstevel@tonic-gatewhich is the "official" way to pass a filehandle: 4018*0Sstevel@tonic-gate 4019*0Sstevel@tonic-gate $query = new CGI(\*STDIN); 4020*0Sstevel@tonic-gate 4021*0Sstevel@tonic-gateYou can also initialize the CGI object with a FileHandle or IO::File 4022*0Sstevel@tonic-gateobject. 4023*0Sstevel@tonic-gate 4024*0Sstevel@tonic-gateIf you are using the function-oriented interface and want to 4025*0Sstevel@tonic-gateinitialize CGI state from a file handle, the way to do this is with 4026*0Sstevel@tonic-gateB<restore_parameters()>. This will (re)initialize the 4027*0Sstevel@tonic-gatedefault CGI object from the indicated file handle. 4028*0Sstevel@tonic-gate 4029*0Sstevel@tonic-gate open (IN,"test.in") || die; 4030*0Sstevel@tonic-gate restore_parameters(IN); 4031*0Sstevel@tonic-gate close IN; 4032*0Sstevel@tonic-gate 4033*0Sstevel@tonic-gateYou can also initialize the query object from an associative array 4034*0Sstevel@tonic-gatereference: 4035*0Sstevel@tonic-gate 4036*0Sstevel@tonic-gate $query = new CGI( {'dinosaur'=>'barney', 4037*0Sstevel@tonic-gate 'song'=>'I love you', 4038*0Sstevel@tonic-gate 'friends'=>[qw/Jessica George Nancy/]} 4039*0Sstevel@tonic-gate ); 4040*0Sstevel@tonic-gate 4041*0Sstevel@tonic-gateor from a properly formatted, URL-escaped query string: 4042*0Sstevel@tonic-gate 4043*0Sstevel@tonic-gate $query = new CGI('dinosaur=barney&color=purple'); 4044*0Sstevel@tonic-gate 4045*0Sstevel@tonic-gateor from a previously existing CGI object (currently this clones the 4046*0Sstevel@tonic-gateparameter list, but none of the other object-specific fields, such as 4047*0Sstevel@tonic-gateautoescaping): 4048*0Sstevel@tonic-gate 4049*0Sstevel@tonic-gate $old_query = new CGI; 4050*0Sstevel@tonic-gate $new_query = new CGI($old_query); 4051*0Sstevel@tonic-gate 4052*0Sstevel@tonic-gateTo create an empty query, initialize it from an empty string or hash: 4053*0Sstevel@tonic-gate 4054*0Sstevel@tonic-gate $empty_query = new CGI(""); 4055*0Sstevel@tonic-gate 4056*0Sstevel@tonic-gate -or- 4057*0Sstevel@tonic-gate 4058*0Sstevel@tonic-gate $empty_query = new CGI({}); 4059*0Sstevel@tonic-gate 4060*0Sstevel@tonic-gate=head2 FETCHING A LIST OF KEYWORDS FROM THE QUERY: 4061*0Sstevel@tonic-gate 4062*0Sstevel@tonic-gate @keywords = $query->keywords 4063*0Sstevel@tonic-gate 4064*0Sstevel@tonic-gateIf the script was invoked as the result of an <ISINDEX> search, the 4065*0Sstevel@tonic-gateparsed keywords can be obtained as an array using the keywords() method. 4066*0Sstevel@tonic-gate 4067*0Sstevel@tonic-gate=head2 FETCHING THE NAMES OF ALL THE PARAMETERS PASSED TO YOUR SCRIPT: 4068*0Sstevel@tonic-gate 4069*0Sstevel@tonic-gate @names = $query->param 4070*0Sstevel@tonic-gate 4071*0Sstevel@tonic-gateIf the script was invoked with a parameter list 4072*0Sstevel@tonic-gate(e.g. "name1=value1&name2=value2&name3=value3"), the param() method 4073*0Sstevel@tonic-gatewill return the parameter names as a list. If the script was invoked 4074*0Sstevel@tonic-gateas an <ISINDEX> script and contains a string without ampersands 4075*0Sstevel@tonic-gate(e.g. "value1+value2+value3") , there will be a single parameter named 4076*0Sstevel@tonic-gate"keywords" containing the "+"-delimited keywords. 4077*0Sstevel@tonic-gate 4078*0Sstevel@tonic-gateNOTE: As of version 1.5, the array of parameter names returned will 4079*0Sstevel@tonic-gatebe in the same order as they were submitted by the browser. 4080*0Sstevel@tonic-gateUsually this order is the same as the order in which the 4081*0Sstevel@tonic-gateparameters are defined in the form (however, this isn't part 4082*0Sstevel@tonic-gateof the spec, and so isn't guaranteed). 4083*0Sstevel@tonic-gate 4084*0Sstevel@tonic-gate=head2 FETCHING THE VALUE OR VALUES OF A SINGLE NAMED PARAMETER: 4085*0Sstevel@tonic-gate 4086*0Sstevel@tonic-gate @values = $query->param('foo'); 4087*0Sstevel@tonic-gate 4088*0Sstevel@tonic-gate -or- 4089*0Sstevel@tonic-gate 4090*0Sstevel@tonic-gate $value = $query->param('foo'); 4091*0Sstevel@tonic-gate 4092*0Sstevel@tonic-gatePass the param() method a single argument to fetch the value of the 4093*0Sstevel@tonic-gatenamed parameter. If the parameter is multivalued (e.g. from multiple 4094*0Sstevel@tonic-gateselections in a scrolling list), you can ask to receive an array. Otherwise 4095*0Sstevel@tonic-gatethe method will return a single value. 4096*0Sstevel@tonic-gate 4097*0Sstevel@tonic-gateIf a value is not given in the query string, as in the queries 4098*0Sstevel@tonic-gate"name1=&name2=" or "name1&name2", it will be returned as an empty 4099*0Sstevel@tonic-gatestring. This feature is new in 2.63. 4100*0Sstevel@tonic-gate 4101*0Sstevel@tonic-gate 4102*0Sstevel@tonic-gateIf the parameter does not exist at all, then param() will return undef 4103*0Sstevel@tonic-gatein a scalar context, and the empty list in a list context. 4104*0Sstevel@tonic-gate 4105*0Sstevel@tonic-gate 4106*0Sstevel@tonic-gate=head2 SETTING THE VALUE(S) OF A NAMED PARAMETER: 4107*0Sstevel@tonic-gate 4108*0Sstevel@tonic-gate $query->param('foo','an','array','of','values'); 4109*0Sstevel@tonic-gate 4110*0Sstevel@tonic-gateThis sets the value for the named parameter 'foo' to an array of 4111*0Sstevel@tonic-gatevalues. This is one way to change the value of a field AFTER 4112*0Sstevel@tonic-gatethe script has been invoked once before. (Another way is with 4113*0Sstevel@tonic-gatethe -override parameter accepted by all methods that generate 4114*0Sstevel@tonic-gateform elements.) 4115*0Sstevel@tonic-gate 4116*0Sstevel@tonic-gateparam() also recognizes a named parameter style of calling described 4117*0Sstevel@tonic-gatein more detail later: 4118*0Sstevel@tonic-gate 4119*0Sstevel@tonic-gate $query->param(-name=>'foo',-values=>['an','array','of','values']); 4120*0Sstevel@tonic-gate 4121*0Sstevel@tonic-gate -or- 4122*0Sstevel@tonic-gate 4123*0Sstevel@tonic-gate $query->param(-name=>'foo',-value=>'the value'); 4124*0Sstevel@tonic-gate 4125*0Sstevel@tonic-gate=head2 APPENDING ADDITIONAL VALUES TO A NAMED PARAMETER: 4126*0Sstevel@tonic-gate 4127*0Sstevel@tonic-gate $query->append(-name=>'foo',-values=>['yet','more','values']); 4128*0Sstevel@tonic-gate 4129*0Sstevel@tonic-gateThis adds a value or list of values to the named parameter. The 4130*0Sstevel@tonic-gatevalues are appended to the end of the parameter if it already exists. 4131*0Sstevel@tonic-gateOtherwise the parameter is created. Note that this method only 4132*0Sstevel@tonic-gaterecognizes the named argument calling syntax. 4133*0Sstevel@tonic-gate 4134*0Sstevel@tonic-gate=head2 IMPORTING ALL PARAMETERS INTO A NAMESPACE: 4135*0Sstevel@tonic-gate 4136*0Sstevel@tonic-gate $query->import_names('R'); 4137*0Sstevel@tonic-gate 4138*0Sstevel@tonic-gateThis creates a series of variables in the 'R' namespace. For example, 4139*0Sstevel@tonic-gate$R::foo, @R:foo. For keyword lists, a variable @R::keywords will appear. 4140*0Sstevel@tonic-gateIf no namespace is given, this method will assume 'Q'. 4141*0Sstevel@tonic-gateWARNING: don't import anything into 'main'; this is a major security 4142*0Sstevel@tonic-gaterisk!!!! 4143*0Sstevel@tonic-gate 4144*0Sstevel@tonic-gateNOTE 1: Variable names are transformed as necessary into legal Perl 4145*0Sstevel@tonic-gatevariable names. All non-legal characters are transformed into 4146*0Sstevel@tonic-gateunderscores. If you need to keep the original names, you should use 4147*0Sstevel@tonic-gatethe param() method instead to access CGI variables by name. 4148*0Sstevel@tonic-gate 4149*0Sstevel@tonic-gateNOTE 2: In older versions, this method was called B<import()>. As of version 2.20, 4150*0Sstevel@tonic-gatethis name has been removed completely to avoid conflict with the built-in 4151*0Sstevel@tonic-gatePerl module B<import> operator. 4152*0Sstevel@tonic-gate 4153*0Sstevel@tonic-gate=head2 DELETING A PARAMETER COMPLETELY: 4154*0Sstevel@tonic-gate 4155*0Sstevel@tonic-gate $query->delete('foo','bar','baz'); 4156*0Sstevel@tonic-gate 4157*0Sstevel@tonic-gateThis completely clears a list of parameters. It sometimes useful for 4158*0Sstevel@tonic-gateresetting parameters that you don't want passed down between script 4159*0Sstevel@tonic-gateinvocations. 4160*0Sstevel@tonic-gate 4161*0Sstevel@tonic-gateIf you are using the function call interface, use "Delete()" instead 4162*0Sstevel@tonic-gateto avoid conflicts with Perl's built-in delete operator. 4163*0Sstevel@tonic-gate 4164*0Sstevel@tonic-gate=head2 DELETING ALL PARAMETERS: 4165*0Sstevel@tonic-gate 4166*0Sstevel@tonic-gate $query->delete_all(); 4167*0Sstevel@tonic-gate 4168*0Sstevel@tonic-gateThis clears the CGI object completely. It might be useful to ensure 4169*0Sstevel@tonic-gatethat all the defaults are taken when you create a fill-out form. 4170*0Sstevel@tonic-gate 4171*0Sstevel@tonic-gateUse Delete_all() instead if you are using the function call interface. 4172*0Sstevel@tonic-gate 4173*0Sstevel@tonic-gate=head2 DIRECT ACCESS TO THE PARAMETER LIST: 4174*0Sstevel@tonic-gate 4175*0Sstevel@tonic-gate $q->param_fetch('address')->[1] = '1313 Mockingbird Lane'; 4176*0Sstevel@tonic-gate unshift @{$q->param_fetch(-name=>'address')},'George Munster'; 4177*0Sstevel@tonic-gate 4178*0Sstevel@tonic-gateIf you need access to the parameter list in a way that isn't covered 4179*0Sstevel@tonic-gateby the methods above, you can obtain a direct reference to it by 4180*0Sstevel@tonic-gatecalling the B<param_fetch()> method with the name of the . This 4181*0Sstevel@tonic-gatewill return an array reference to the named parameters, which you then 4182*0Sstevel@tonic-gatecan manipulate in any way you like. 4183*0Sstevel@tonic-gate 4184*0Sstevel@tonic-gateYou can also use a named argument style using the B<-name> argument. 4185*0Sstevel@tonic-gate 4186*0Sstevel@tonic-gate=head2 FETCHING THE PARAMETER LIST AS A HASH: 4187*0Sstevel@tonic-gate 4188*0Sstevel@tonic-gate $params = $q->Vars; 4189*0Sstevel@tonic-gate print $params->{'address'}; 4190*0Sstevel@tonic-gate @foo = split("\0",$params->{'foo'}); 4191*0Sstevel@tonic-gate %params = $q->Vars; 4192*0Sstevel@tonic-gate 4193*0Sstevel@tonic-gate use CGI ':cgi-lib'; 4194*0Sstevel@tonic-gate $params = Vars; 4195*0Sstevel@tonic-gate 4196*0Sstevel@tonic-gateMany people want to fetch the entire parameter list as a hash in which 4197*0Sstevel@tonic-gatethe keys are the names of the CGI parameters, and the values are the 4198*0Sstevel@tonic-gateparameters' values. The Vars() method does this. Called in a scalar 4199*0Sstevel@tonic-gatecontext, it returns the parameter list as a tied hash reference. 4200*0Sstevel@tonic-gateChanging a key changes the value of the parameter in the underlying 4201*0Sstevel@tonic-gateCGI parameter list. Called in a list context, it returns the 4202*0Sstevel@tonic-gateparameter list as an ordinary hash. This allows you to read the 4203*0Sstevel@tonic-gatecontents of the parameter list, but not to change it. 4204*0Sstevel@tonic-gate 4205*0Sstevel@tonic-gateWhen using this, the thing you must watch out for are multivalued CGI 4206*0Sstevel@tonic-gateparameters. Because a hash cannot distinguish between scalar and 4207*0Sstevel@tonic-gatelist context, multivalued parameters will be returned as a packed 4208*0Sstevel@tonic-gatestring, separated by the "\0" (null) character. You must split this 4209*0Sstevel@tonic-gatepacked string in order to get at the individual values. This is the 4210*0Sstevel@tonic-gateconvention introduced long ago by Steve Brenner in his cgi-lib.pl 4211*0Sstevel@tonic-gatemodule for Perl version 4. 4212*0Sstevel@tonic-gate 4213*0Sstevel@tonic-gateIf you wish to use Vars() as a function, import the I<:cgi-lib> set of 4214*0Sstevel@tonic-gatefunction calls (also see the section on CGI-LIB compatibility). 4215*0Sstevel@tonic-gate 4216*0Sstevel@tonic-gate=head2 SAVING THE STATE OF THE SCRIPT TO A FILE: 4217*0Sstevel@tonic-gate 4218*0Sstevel@tonic-gate $query->save(FILEHANDLE) 4219*0Sstevel@tonic-gate 4220*0Sstevel@tonic-gateThis will write the current state of the form to the provided 4221*0Sstevel@tonic-gatefilehandle. You can read it back in by providing a filehandle 4222*0Sstevel@tonic-gateto the new() method. Note that the filehandle can be a file, a pipe, 4223*0Sstevel@tonic-gateor whatever! 4224*0Sstevel@tonic-gate 4225*0Sstevel@tonic-gateThe format of the saved file is: 4226*0Sstevel@tonic-gate 4227*0Sstevel@tonic-gate NAME1=VALUE1 4228*0Sstevel@tonic-gate NAME1=VALUE1' 4229*0Sstevel@tonic-gate NAME2=VALUE2 4230*0Sstevel@tonic-gate NAME3=VALUE3 4231*0Sstevel@tonic-gate = 4232*0Sstevel@tonic-gate 4233*0Sstevel@tonic-gateBoth name and value are URL escaped. Multi-valued CGI parameters are 4234*0Sstevel@tonic-gaterepresented as repeated names. A session record is delimited by a 4235*0Sstevel@tonic-gatesingle = symbol. You can write out multiple records and read them 4236*0Sstevel@tonic-gateback in with several calls to B<new>. You can do this across several 4237*0Sstevel@tonic-gatesessions by opening the file in append mode, allowing you to create 4238*0Sstevel@tonic-gateprimitive guest books, or to keep a history of users' queries. Here's 4239*0Sstevel@tonic-gatea short example of creating multiple session records: 4240*0Sstevel@tonic-gate 4241*0Sstevel@tonic-gate use CGI; 4242*0Sstevel@tonic-gate 4243*0Sstevel@tonic-gate open (OUT,">>test.out") || die; 4244*0Sstevel@tonic-gate $records = 5; 4245*0Sstevel@tonic-gate foreach (0..$records) { 4246*0Sstevel@tonic-gate my $q = new CGI; 4247*0Sstevel@tonic-gate $q->param(-name=>'counter',-value=>$_); 4248*0Sstevel@tonic-gate $q->save(OUT); 4249*0Sstevel@tonic-gate } 4250*0Sstevel@tonic-gate close OUT; 4251*0Sstevel@tonic-gate 4252*0Sstevel@tonic-gate # reopen for reading 4253*0Sstevel@tonic-gate open (IN,"test.out") || die; 4254*0Sstevel@tonic-gate while (!eof(IN)) { 4255*0Sstevel@tonic-gate my $q = new CGI(IN); 4256*0Sstevel@tonic-gate print $q->param('counter'),"\n"; 4257*0Sstevel@tonic-gate } 4258*0Sstevel@tonic-gate 4259*0Sstevel@tonic-gateThe file format used for save/restore is identical to that used by the 4260*0Sstevel@tonic-gateWhitehead Genome Center's data exchange format "Boulderio", and can be 4261*0Sstevel@tonic-gatemanipulated and even databased using Boulderio utilities. See 4262*0Sstevel@tonic-gate 4263*0Sstevel@tonic-gate http://stein.cshl.org/boulder/ 4264*0Sstevel@tonic-gate 4265*0Sstevel@tonic-gatefor further details. 4266*0Sstevel@tonic-gate 4267*0Sstevel@tonic-gateIf you wish to use this method from the function-oriented (non-OO) 4268*0Sstevel@tonic-gateinterface, the exported name for this method is B<save_parameters()>. 4269*0Sstevel@tonic-gate 4270*0Sstevel@tonic-gate=head2 RETRIEVING CGI ERRORS 4271*0Sstevel@tonic-gate 4272*0Sstevel@tonic-gateErrors can occur while processing user input, particularly when 4273*0Sstevel@tonic-gateprocessing uploaded files. When these errors occur, CGI will stop 4274*0Sstevel@tonic-gateprocessing and return an empty parameter list. You can test for 4275*0Sstevel@tonic-gatethe existence and nature of errors using the I<cgi_error()> function. 4276*0Sstevel@tonic-gateThe error messages are formatted as HTTP status codes. You can either 4277*0Sstevel@tonic-gateincorporate the error text into an HTML page, or use it as the value 4278*0Sstevel@tonic-gateof the HTTP status: 4279*0Sstevel@tonic-gate 4280*0Sstevel@tonic-gate my $error = $q->cgi_error; 4281*0Sstevel@tonic-gate if ($error) { 4282*0Sstevel@tonic-gate print $q->header(-status=>$error), 4283*0Sstevel@tonic-gate $q->start_html('Problems'), 4284*0Sstevel@tonic-gate $q->h2('Request not processed'), 4285*0Sstevel@tonic-gate $q->strong($error); 4286*0Sstevel@tonic-gate exit 0; 4287*0Sstevel@tonic-gate } 4288*0Sstevel@tonic-gate 4289*0Sstevel@tonic-gateWhen using the function-oriented interface (see the next section), 4290*0Sstevel@tonic-gateerrors may only occur the first time you call I<param()>. Be ready 4291*0Sstevel@tonic-gatefor this! 4292*0Sstevel@tonic-gate 4293*0Sstevel@tonic-gate=head2 USING THE FUNCTION-ORIENTED INTERFACE 4294*0Sstevel@tonic-gate 4295*0Sstevel@tonic-gateTo use the function-oriented interface, you must specify which CGI.pm 4296*0Sstevel@tonic-gateroutines or sets of routines to import into your script's namespace. 4297*0Sstevel@tonic-gateThere is a small overhead associated with this importation, but it 4298*0Sstevel@tonic-gateisn't much. 4299*0Sstevel@tonic-gate 4300*0Sstevel@tonic-gate use CGI <list of methods>; 4301*0Sstevel@tonic-gate 4302*0Sstevel@tonic-gateThe listed methods will be imported into the current package; you can 4303*0Sstevel@tonic-gatecall them directly without creating a CGI object first. This example 4304*0Sstevel@tonic-gateshows how to import the B<param()> and B<header()> 4305*0Sstevel@tonic-gatemethods, and then use them directly: 4306*0Sstevel@tonic-gate 4307*0Sstevel@tonic-gate use CGI 'param','header'; 4308*0Sstevel@tonic-gate print header('text/plain'); 4309*0Sstevel@tonic-gate $zipcode = param('zipcode'); 4310*0Sstevel@tonic-gate 4311*0Sstevel@tonic-gateMore frequently, you'll import common sets of functions by referring 4312*0Sstevel@tonic-gateto the groups by name. All function sets are preceded with a ":" 4313*0Sstevel@tonic-gatecharacter as in ":html3" (for tags defined in the HTML 3 standard). 4314*0Sstevel@tonic-gate 4315*0Sstevel@tonic-gateHere is a list of the function sets you can import: 4316*0Sstevel@tonic-gate 4317*0Sstevel@tonic-gate=over 4 4318*0Sstevel@tonic-gate 4319*0Sstevel@tonic-gate=item B<:cgi> 4320*0Sstevel@tonic-gate 4321*0Sstevel@tonic-gateImport all CGI-handling methods, such as B<param()>, B<path_info()> 4322*0Sstevel@tonic-gateand the like. 4323*0Sstevel@tonic-gate 4324*0Sstevel@tonic-gate=item B<:form> 4325*0Sstevel@tonic-gate 4326*0Sstevel@tonic-gateImport all fill-out form generating methods, such as B<textfield()>. 4327*0Sstevel@tonic-gate 4328*0Sstevel@tonic-gate=item B<:html2> 4329*0Sstevel@tonic-gate 4330*0Sstevel@tonic-gateImport all methods that generate HTML 2.0 standard elements. 4331*0Sstevel@tonic-gate 4332*0Sstevel@tonic-gate=item B<:html3> 4333*0Sstevel@tonic-gate 4334*0Sstevel@tonic-gateImport all methods that generate HTML 3.0 elements (such as 4335*0Sstevel@tonic-gate<table>, <super> and <sub>). 4336*0Sstevel@tonic-gate 4337*0Sstevel@tonic-gate=item B<:html4> 4338*0Sstevel@tonic-gate 4339*0Sstevel@tonic-gateImport all methods that generate HTML 4 elements (such as 4340*0Sstevel@tonic-gate<abbrev>, <acronym> and <thead>). 4341*0Sstevel@tonic-gate 4342*0Sstevel@tonic-gate=item B<:netscape> 4343*0Sstevel@tonic-gate 4344*0Sstevel@tonic-gateImport all methods that generate Netscape-specific HTML extensions. 4345*0Sstevel@tonic-gate 4346*0Sstevel@tonic-gate=item B<:html> 4347*0Sstevel@tonic-gate 4348*0Sstevel@tonic-gateImport all HTML-generating shortcuts (i.e. 'html2' + 'html3' + 4349*0Sstevel@tonic-gate'netscape')... 4350*0Sstevel@tonic-gate 4351*0Sstevel@tonic-gate=item B<:standard> 4352*0Sstevel@tonic-gate 4353*0Sstevel@tonic-gateImport "standard" features, 'html2', 'html3', 'html4', 'form' and 'cgi'. 4354*0Sstevel@tonic-gate 4355*0Sstevel@tonic-gate=item B<:all> 4356*0Sstevel@tonic-gate 4357*0Sstevel@tonic-gateImport all the available methods. For the full list, see the CGI.pm 4358*0Sstevel@tonic-gatecode, where the variable %EXPORT_TAGS is defined. 4359*0Sstevel@tonic-gate 4360*0Sstevel@tonic-gate=back 4361*0Sstevel@tonic-gate 4362*0Sstevel@tonic-gateIf you import a function name that is not part of CGI.pm, the module 4363*0Sstevel@tonic-gatewill treat it as a new HTML tag and generate the appropriate 4364*0Sstevel@tonic-gatesubroutine. You can then use it like any other HTML tag. This is to 4365*0Sstevel@tonic-gateprovide for the rapidly-evolving HTML "standard." For example, say 4366*0Sstevel@tonic-gateMicrosoft comes out with a new tag called <gradient> (which causes the 4367*0Sstevel@tonic-gateuser's desktop to be flooded with a rotating gradient fill until his 4368*0Sstevel@tonic-gatemachine reboots). You don't need to wait for a new version of CGI.pm 4369*0Sstevel@tonic-gateto start using it immediately: 4370*0Sstevel@tonic-gate 4371*0Sstevel@tonic-gate use CGI qw/:standard :html3 gradient/; 4372*0Sstevel@tonic-gate print gradient({-start=>'red',-end=>'blue'}); 4373*0Sstevel@tonic-gate 4374*0Sstevel@tonic-gateNote that in the interests of execution speed CGI.pm does B<not> use 4375*0Sstevel@tonic-gatethe standard L<Exporter> syntax for specifying load symbols. This may 4376*0Sstevel@tonic-gatechange in the future. 4377*0Sstevel@tonic-gate 4378*0Sstevel@tonic-gateIf you import any of the state-maintaining CGI or form-generating 4379*0Sstevel@tonic-gatemethods, a default CGI object will be created and initialized 4380*0Sstevel@tonic-gateautomatically the first time you use any of the methods that require 4381*0Sstevel@tonic-gateone to be present. This includes B<param()>, B<textfield()>, 4382*0Sstevel@tonic-gateB<submit()> and the like. (If you need direct access to the CGI 4383*0Sstevel@tonic-gateobject, you can find it in the global variable B<$CGI::Q>). By 4384*0Sstevel@tonic-gateimporting CGI.pm methods, you can create visually elegant scripts: 4385*0Sstevel@tonic-gate 4386*0Sstevel@tonic-gate use CGI qw/:standard/; 4387*0Sstevel@tonic-gate print 4388*0Sstevel@tonic-gate header, 4389*0Sstevel@tonic-gate start_html('Simple Script'), 4390*0Sstevel@tonic-gate h1('Simple Script'), 4391*0Sstevel@tonic-gate start_form, 4392*0Sstevel@tonic-gate "What's your name? ",textfield('name'),p, 4393*0Sstevel@tonic-gate "What's the combination?", 4394*0Sstevel@tonic-gate checkbox_group(-name=>'words', 4395*0Sstevel@tonic-gate -values=>['eenie','meenie','minie','moe'], 4396*0Sstevel@tonic-gate -defaults=>['eenie','moe']),p, 4397*0Sstevel@tonic-gate "What's your favorite color?", 4398*0Sstevel@tonic-gate popup_menu(-name=>'color', 4399*0Sstevel@tonic-gate -values=>['red','green','blue','chartreuse']),p, 4400*0Sstevel@tonic-gate submit, 4401*0Sstevel@tonic-gate end_form, 4402*0Sstevel@tonic-gate hr,"\n"; 4403*0Sstevel@tonic-gate 4404*0Sstevel@tonic-gate if (param) { 4405*0Sstevel@tonic-gate print 4406*0Sstevel@tonic-gate "Your name is ",em(param('name')),p, 4407*0Sstevel@tonic-gate "The keywords are: ",em(join(", ",param('words'))),p, 4408*0Sstevel@tonic-gate "Your favorite color is ",em(param('color')),".\n"; 4409*0Sstevel@tonic-gate } 4410*0Sstevel@tonic-gate print end_html; 4411*0Sstevel@tonic-gate 4412*0Sstevel@tonic-gate=head2 PRAGMAS 4413*0Sstevel@tonic-gate 4414*0Sstevel@tonic-gateIn addition to the function sets, there are a number of pragmas that 4415*0Sstevel@tonic-gateyou can import. Pragmas, which are always preceded by a hyphen, 4416*0Sstevel@tonic-gatechange the way that CGI.pm functions in various ways. Pragmas, 4417*0Sstevel@tonic-gatefunction sets, and individual functions can all be imported in the 4418*0Sstevel@tonic-gatesame use() line. For example, the following use statement imports the 4419*0Sstevel@tonic-gatestandard set of functions and enables debugging mode (pragma 4420*0Sstevel@tonic-gate-debug): 4421*0Sstevel@tonic-gate 4422*0Sstevel@tonic-gate use CGI qw/:standard -debug/; 4423*0Sstevel@tonic-gate 4424*0Sstevel@tonic-gateThe current list of pragmas is as follows: 4425*0Sstevel@tonic-gate 4426*0Sstevel@tonic-gate=over 4 4427*0Sstevel@tonic-gate 4428*0Sstevel@tonic-gate=item -any 4429*0Sstevel@tonic-gate 4430*0Sstevel@tonic-gateWhen you I<use CGI -any>, then any method that the query object 4431*0Sstevel@tonic-gatedoesn't recognize will be interpreted as a new HTML tag. This allows 4432*0Sstevel@tonic-gateyou to support the next I<ad hoc> Netscape or Microsoft HTML 4433*0Sstevel@tonic-gateextension. This lets you go wild with new and unsupported tags: 4434*0Sstevel@tonic-gate 4435*0Sstevel@tonic-gate use CGI qw(-any); 4436*0Sstevel@tonic-gate $q=new CGI; 4437*0Sstevel@tonic-gate print $q->gradient({speed=>'fast',start=>'red',end=>'blue'}); 4438*0Sstevel@tonic-gate 4439*0Sstevel@tonic-gateSince using <cite>any</cite> causes any mistyped method name 4440*0Sstevel@tonic-gateto be interpreted as an HTML tag, use it with care or not at 4441*0Sstevel@tonic-gateall. 4442*0Sstevel@tonic-gate 4443*0Sstevel@tonic-gate=item -compile 4444*0Sstevel@tonic-gate 4445*0Sstevel@tonic-gateThis causes the indicated autoloaded methods to be compiled up front, 4446*0Sstevel@tonic-gaterather than deferred to later. This is useful for scripts that run 4447*0Sstevel@tonic-gatefor an extended period of time under FastCGI or mod_perl, and for 4448*0Sstevel@tonic-gatethose destined to be crunched by Malcom Beattie's Perl compiler. Use 4449*0Sstevel@tonic-gateit in conjunction with the methods or method families you plan to use. 4450*0Sstevel@tonic-gate 4451*0Sstevel@tonic-gate use CGI qw(-compile :standard :html3); 4452*0Sstevel@tonic-gate 4453*0Sstevel@tonic-gateor even 4454*0Sstevel@tonic-gate 4455*0Sstevel@tonic-gate use CGI qw(-compile :all); 4456*0Sstevel@tonic-gate 4457*0Sstevel@tonic-gateNote that using the -compile pragma in this way will always have 4458*0Sstevel@tonic-gatethe effect of importing the compiled functions into the current 4459*0Sstevel@tonic-gatenamespace. If you want to compile without importing use the 4460*0Sstevel@tonic-gatecompile() method instead: 4461*0Sstevel@tonic-gate 4462*0Sstevel@tonic-gate use CGI(); 4463*0Sstevel@tonic-gate CGI->compile(); 4464*0Sstevel@tonic-gate 4465*0Sstevel@tonic-gateThis is particularly useful in a mod_perl environment, in which you 4466*0Sstevel@tonic-gatemight want to precompile all CGI routines in a startup script, and 4467*0Sstevel@tonic-gatethen import the functions individually in each mod_perl script. 4468*0Sstevel@tonic-gate 4469*0Sstevel@tonic-gate=item -nosticky 4470*0Sstevel@tonic-gate 4471*0Sstevel@tonic-gateThis makes CGI.pm not generating the hidden fields .submit 4472*0Sstevel@tonic-gateand .cgifields. It is very useful if you don't want to 4473*0Sstevel@tonic-gatehave the hidden fields appear in the querystring in a GET method. 4474*0Sstevel@tonic-gateFor example, a search script generated this way will have 4475*0Sstevel@tonic-gatea very nice url with search parameters for bookmarking. 4476*0Sstevel@tonic-gate 4477*0Sstevel@tonic-gate=item -no_undef_params 4478*0Sstevel@tonic-gate 4479*0Sstevel@tonic-gateThis keeps CGI.pm from including undef params in the parameter list. 4480*0Sstevel@tonic-gate 4481*0Sstevel@tonic-gate=item -no_xhtml 4482*0Sstevel@tonic-gate 4483*0Sstevel@tonic-gateBy default, CGI.pm versions 2.69 and higher emit XHTML 4484*0Sstevel@tonic-gate(http://www.w3.org/TR/xhtml1/). The -no_xhtml pragma disables this 4485*0Sstevel@tonic-gatefeature. Thanks to Michalis Kabrianis <kabrianis@hellug.gr> for this 4486*0Sstevel@tonic-gatefeature. 4487*0Sstevel@tonic-gate 4488*0Sstevel@tonic-gate=item -nph 4489*0Sstevel@tonic-gate 4490*0Sstevel@tonic-gateThis makes CGI.pm produce a header appropriate for an NPH (no 4491*0Sstevel@tonic-gateparsed header) script. You may need to do other things as well 4492*0Sstevel@tonic-gateto tell the server that the script is NPH. See the discussion 4493*0Sstevel@tonic-gateof NPH scripts below. 4494*0Sstevel@tonic-gate 4495*0Sstevel@tonic-gate=item -newstyle_urls 4496*0Sstevel@tonic-gate 4497*0Sstevel@tonic-gateSeparate the name=value pairs in CGI parameter query strings with 4498*0Sstevel@tonic-gatesemicolons rather than ampersands. For example: 4499*0Sstevel@tonic-gate 4500*0Sstevel@tonic-gate ?name=fred;age=24;favorite_color=3 4501*0Sstevel@tonic-gate 4502*0Sstevel@tonic-gateSemicolon-delimited query strings are always accepted, but will not be 4503*0Sstevel@tonic-gateemitted by self_url() and query_string() unless the -newstyle_urls 4504*0Sstevel@tonic-gatepragma is specified. 4505*0Sstevel@tonic-gate 4506*0Sstevel@tonic-gateThis became the default in version 2.64. 4507*0Sstevel@tonic-gate 4508*0Sstevel@tonic-gate=item -oldstyle_urls 4509*0Sstevel@tonic-gate 4510*0Sstevel@tonic-gateSeparate the name=value pairs in CGI parameter query strings with 4511*0Sstevel@tonic-gateampersands rather than semicolons. This is no longer the default. 4512*0Sstevel@tonic-gate 4513*0Sstevel@tonic-gate=item -autoload 4514*0Sstevel@tonic-gate 4515*0Sstevel@tonic-gateThis overrides the autoloader so that any function in your program 4516*0Sstevel@tonic-gatethat is not recognized is referred to CGI.pm for possible evaluation. 4517*0Sstevel@tonic-gateThis allows you to use all the CGI.pm functions without adding them to 4518*0Sstevel@tonic-gateyour symbol table, which is of concern for mod_perl users who are 4519*0Sstevel@tonic-gateworried about memory consumption. I<Warning:> when 4520*0Sstevel@tonic-gateI<-autoload> is in effect, you cannot use "poetry mode" 4521*0Sstevel@tonic-gate(functions without the parenthesis). Use I<hr()> rather 4522*0Sstevel@tonic-gatethan I<hr>, or add something like I<use subs qw/hr p header/> 4523*0Sstevel@tonic-gateto the top of your script. 4524*0Sstevel@tonic-gate 4525*0Sstevel@tonic-gate=item -no_debug 4526*0Sstevel@tonic-gate 4527*0Sstevel@tonic-gateThis turns off the command-line processing features. If you want to 4528*0Sstevel@tonic-gaterun a CGI.pm script from the command line to produce HTML, and you 4529*0Sstevel@tonic-gatedon't want it to read CGI parameters from the command line or STDIN, 4530*0Sstevel@tonic-gatethen use this pragma: 4531*0Sstevel@tonic-gate 4532*0Sstevel@tonic-gate use CGI qw(-no_debug :standard); 4533*0Sstevel@tonic-gate 4534*0Sstevel@tonic-gate=item -debug 4535*0Sstevel@tonic-gate 4536*0Sstevel@tonic-gateThis turns on full debugging. In addition to reading CGI arguments 4537*0Sstevel@tonic-gatefrom the command-line processing, CGI.pm will pause and try to read 4538*0Sstevel@tonic-gatearguments from STDIN, producing the message "(offline mode: enter 4539*0Sstevel@tonic-gatename=value pairs on standard input)" features. 4540*0Sstevel@tonic-gate 4541*0Sstevel@tonic-gateSee the section on debugging for more details. 4542*0Sstevel@tonic-gate 4543*0Sstevel@tonic-gate=item -private_tempfiles 4544*0Sstevel@tonic-gate 4545*0Sstevel@tonic-gateCGI.pm can process uploaded file. Ordinarily it spools the uploaded 4546*0Sstevel@tonic-gatefile to a temporary directory, then deletes the file when done. 4547*0Sstevel@tonic-gateHowever, this opens the risk of eavesdropping as described in the file 4548*0Sstevel@tonic-gateupload section. Another CGI script author could peek at this data 4549*0Sstevel@tonic-gateduring the upload, even if it is confidential information. On Unix 4550*0Sstevel@tonic-gatesystems, the -private_tempfiles pragma will cause the temporary file 4551*0Sstevel@tonic-gateto be unlinked as soon as it is opened and before any data is written 4552*0Sstevel@tonic-gateinto it, reducing, but not eliminating the risk of eavesdropping 4553*0Sstevel@tonic-gate(there is still a potential race condition). To make life harder for 4554*0Sstevel@tonic-gatethe attacker, the program chooses tempfile names by calculating a 32 4555*0Sstevel@tonic-gatebit checksum of the incoming HTTP headers. 4556*0Sstevel@tonic-gate 4557*0Sstevel@tonic-gateTo ensure that the temporary file cannot be read by other CGI scripts, 4558*0Sstevel@tonic-gateuse suEXEC or a CGI wrapper program to run your script. The temporary 4559*0Sstevel@tonic-gatefile is created with mode 0600 (neither world nor group readable). 4560*0Sstevel@tonic-gate 4561*0Sstevel@tonic-gateThe temporary directory is selected using the following algorithm: 4562*0Sstevel@tonic-gate 4563*0Sstevel@tonic-gate 1. if the current user (e.g. "nobody") has a directory named 4564*0Sstevel@tonic-gate "tmp" in its home directory, use that (Unix systems only). 4565*0Sstevel@tonic-gate 4566*0Sstevel@tonic-gate 2. if the environment variable TMPDIR exists, use the location 4567*0Sstevel@tonic-gate indicated. 4568*0Sstevel@tonic-gate 4569*0Sstevel@tonic-gate 3. Otherwise try the locations /usr/tmp, /var/tmp, C:\temp, 4570*0Sstevel@tonic-gate /tmp, /temp, ::Temporary Items, and \WWW_ROOT. 4571*0Sstevel@tonic-gate 4572*0Sstevel@tonic-gateEach of these locations is checked that it is a directory and is 4573*0Sstevel@tonic-gatewritable. If not, the algorithm tries the next choice. 4574*0Sstevel@tonic-gate 4575*0Sstevel@tonic-gate=back 4576*0Sstevel@tonic-gate 4577*0Sstevel@tonic-gate=head2 SPECIAL FORMS FOR IMPORTING HTML-TAG FUNCTIONS 4578*0Sstevel@tonic-gate 4579*0Sstevel@tonic-gateMany of the methods generate HTML tags. As described below, tag 4580*0Sstevel@tonic-gatefunctions automatically generate both the opening and closing tags. 4581*0Sstevel@tonic-gateFor example: 4582*0Sstevel@tonic-gate 4583*0Sstevel@tonic-gate print h1('Level 1 Header'); 4584*0Sstevel@tonic-gate 4585*0Sstevel@tonic-gateproduces 4586*0Sstevel@tonic-gate 4587*0Sstevel@tonic-gate <h1>Level 1 Header</h1> 4588*0Sstevel@tonic-gate 4589*0Sstevel@tonic-gateThere will be some times when you want to produce the start and end 4590*0Sstevel@tonic-gatetags yourself. In this case, you can use the form start_I<tag_name> 4591*0Sstevel@tonic-gateand end_I<tag_name>, as in: 4592*0Sstevel@tonic-gate 4593*0Sstevel@tonic-gate print start_h1,'Level 1 Header',end_h1; 4594*0Sstevel@tonic-gate 4595*0Sstevel@tonic-gateWith a few exceptions (described below), start_I<tag_name> and 4596*0Sstevel@tonic-gateend_I<tag_name> functions are not generated automatically when you 4597*0Sstevel@tonic-gateI<use CGI>. However, you can specify the tags you want to generate 4598*0Sstevel@tonic-gateI<start/end> functions for by putting an asterisk in front of their 4599*0Sstevel@tonic-gatename, or, alternatively, requesting either "start_I<tag_name>" or 4600*0Sstevel@tonic-gate"end_I<tag_name>" in the import list. 4601*0Sstevel@tonic-gate 4602*0Sstevel@tonic-gateExample: 4603*0Sstevel@tonic-gate 4604*0Sstevel@tonic-gate use CGI qw/:standard *table start_ul/; 4605*0Sstevel@tonic-gate 4606*0Sstevel@tonic-gateIn this example, the following functions are generated in addition to 4607*0Sstevel@tonic-gatethe standard ones: 4608*0Sstevel@tonic-gate 4609*0Sstevel@tonic-gate=over 4 4610*0Sstevel@tonic-gate 4611*0Sstevel@tonic-gate=item 1. start_table() (generates a <table> tag) 4612*0Sstevel@tonic-gate 4613*0Sstevel@tonic-gate=item 2. end_table() (generates a </table> tag) 4614*0Sstevel@tonic-gate 4615*0Sstevel@tonic-gate=item 3. start_ul() (generates a <ul> tag) 4616*0Sstevel@tonic-gate 4617*0Sstevel@tonic-gate=item 4. end_ul() (generates a </ul> tag) 4618*0Sstevel@tonic-gate 4619*0Sstevel@tonic-gate=back 4620*0Sstevel@tonic-gate 4621*0Sstevel@tonic-gate=head1 GENERATING DYNAMIC DOCUMENTS 4622*0Sstevel@tonic-gate 4623*0Sstevel@tonic-gateMost of CGI.pm's functions deal with creating documents on the fly. 4624*0Sstevel@tonic-gateGenerally you will produce the HTTP header first, followed by the 4625*0Sstevel@tonic-gatedocument itself. CGI.pm provides functions for generating HTTP 4626*0Sstevel@tonic-gateheaders of various types as well as for generating HTML. For creating 4627*0Sstevel@tonic-gateGIF images, see the GD.pm module. 4628*0Sstevel@tonic-gate 4629*0Sstevel@tonic-gateEach of these functions produces a fragment of HTML or HTTP which you 4630*0Sstevel@tonic-gatecan print out directly so that it displays in the browser window, 4631*0Sstevel@tonic-gateappend to a string, or save to a file for later use. 4632*0Sstevel@tonic-gate 4633*0Sstevel@tonic-gate=head2 CREATING A STANDARD HTTP HEADER: 4634*0Sstevel@tonic-gate 4635*0Sstevel@tonic-gateNormally the first thing you will do in any CGI script is print out an 4636*0Sstevel@tonic-gateHTTP header. This tells the browser what type of document to expect, 4637*0Sstevel@tonic-gateand gives other optional information, such as the language, expiration 4638*0Sstevel@tonic-gatedate, and whether to cache the document. The header can also be 4639*0Sstevel@tonic-gatemanipulated for special purposes, such as server push and pay per view 4640*0Sstevel@tonic-gatepages. 4641*0Sstevel@tonic-gate 4642*0Sstevel@tonic-gate print $query->header; 4643*0Sstevel@tonic-gate 4644*0Sstevel@tonic-gate -or- 4645*0Sstevel@tonic-gate 4646*0Sstevel@tonic-gate print $query->header('image/gif'); 4647*0Sstevel@tonic-gate 4648*0Sstevel@tonic-gate -or- 4649*0Sstevel@tonic-gate 4650*0Sstevel@tonic-gate print $query->header('text/html','204 No response'); 4651*0Sstevel@tonic-gate 4652*0Sstevel@tonic-gate -or- 4653*0Sstevel@tonic-gate 4654*0Sstevel@tonic-gate print $query->header(-type=>'image/gif', 4655*0Sstevel@tonic-gate -nph=>1, 4656*0Sstevel@tonic-gate -status=>'402 Payment required', 4657*0Sstevel@tonic-gate -expires=>'+3d', 4658*0Sstevel@tonic-gate -cookie=>$cookie, 4659*0Sstevel@tonic-gate -charset=>'utf-7', 4660*0Sstevel@tonic-gate -attachment=>'foo.gif', 4661*0Sstevel@tonic-gate -Cost=>'$2.00'); 4662*0Sstevel@tonic-gate 4663*0Sstevel@tonic-gateheader() returns the Content-type: header. You can provide your own 4664*0Sstevel@tonic-gateMIME type if you choose, otherwise it defaults to text/html. An 4665*0Sstevel@tonic-gateoptional second parameter specifies the status code and a human-readable 4666*0Sstevel@tonic-gatemessage. For example, you can specify 204, "No response" to create a 4667*0Sstevel@tonic-gatescript that tells the browser to do nothing at all. 4668*0Sstevel@tonic-gate 4669*0Sstevel@tonic-gateThe last example shows the named argument style for passing arguments 4670*0Sstevel@tonic-gateto the CGI methods using named parameters. Recognized parameters are 4671*0Sstevel@tonic-gateB<-type>, B<-status>, B<-expires>, and B<-cookie>. Any other named 4672*0Sstevel@tonic-gateparameters will be stripped of their initial hyphens and turned into 4673*0Sstevel@tonic-gateheader fields, allowing you to specify any HTTP header you desire. 4674*0Sstevel@tonic-gateInternal underscores will be turned into hyphens: 4675*0Sstevel@tonic-gate 4676*0Sstevel@tonic-gate print $query->header(-Content_length=>3002); 4677*0Sstevel@tonic-gate 4678*0Sstevel@tonic-gateMost browsers will not cache the output from CGI scripts. Every time 4679*0Sstevel@tonic-gatethe browser reloads the page, the script is invoked anew. You can 4680*0Sstevel@tonic-gatechange this behavior with the B<-expires> parameter. When you specify 4681*0Sstevel@tonic-gatean absolute or relative expiration interval with this parameter, some 4682*0Sstevel@tonic-gatebrowsers and proxy servers will cache the script's output until the 4683*0Sstevel@tonic-gateindicated expiration date. The following forms are all valid for the 4684*0Sstevel@tonic-gate-expires field: 4685*0Sstevel@tonic-gate 4686*0Sstevel@tonic-gate +30s 30 seconds from now 4687*0Sstevel@tonic-gate +10m ten minutes from now 4688*0Sstevel@tonic-gate +1h one hour from now 4689*0Sstevel@tonic-gate -1d yesterday (i.e. "ASAP!") 4690*0Sstevel@tonic-gate now immediately 4691*0Sstevel@tonic-gate +3M in three months 4692*0Sstevel@tonic-gate +10y in ten years time 4693*0Sstevel@tonic-gate Thursday, 25-Apr-1999 00:40:33 GMT at the indicated time & date 4694*0Sstevel@tonic-gate 4695*0Sstevel@tonic-gateThe B<-cookie> parameter generates a header that tells the browser to provide 4696*0Sstevel@tonic-gatea "magic cookie" during all subsequent transactions with your script. 4697*0Sstevel@tonic-gateNetscape cookies have a special format that includes interesting attributes 4698*0Sstevel@tonic-gatesuch as expiration time. Use the cookie() method to create and retrieve 4699*0Sstevel@tonic-gatesession cookies. 4700*0Sstevel@tonic-gate 4701*0Sstevel@tonic-gateThe B<-nph> parameter, if set to a true value, will issue the correct 4702*0Sstevel@tonic-gateheaders to work with a NPH (no-parse-header) script. This is important 4703*0Sstevel@tonic-gateto use with certain servers that expect all their scripts to be NPH. 4704*0Sstevel@tonic-gate 4705*0Sstevel@tonic-gateThe B<-charset> parameter can be used to control the character set 4706*0Sstevel@tonic-gatesent to the browser. If not provided, defaults to ISO-8859-1. As a 4707*0Sstevel@tonic-gateside effect, this sets the charset() method as well. 4708*0Sstevel@tonic-gate 4709*0Sstevel@tonic-gateThe B<-attachment> parameter can be used to turn the page into an 4710*0Sstevel@tonic-gateattachment. Instead of displaying the page, some browsers will prompt 4711*0Sstevel@tonic-gatethe user to save it to disk. The value of the argument is the 4712*0Sstevel@tonic-gatesuggested name for the saved file. In order for this to work, you may 4713*0Sstevel@tonic-gatehave to set the B<-type> to "application/octet-stream". 4714*0Sstevel@tonic-gate 4715*0Sstevel@tonic-gateThe B<-p3p> parameter will add a P3P tag to the outgoing header. The 4716*0Sstevel@tonic-gateparameter can be an arrayref or a space-delimited string of P3P tags. 4717*0Sstevel@tonic-gateFor example: 4718*0Sstevel@tonic-gate 4719*0Sstevel@tonic-gate print header(-p3p=>[qw(CAO DSP LAW CURa)]); 4720*0Sstevel@tonic-gate print header(-p3p=>'CAO DSP LAW CURa'); 4721*0Sstevel@tonic-gate 4722*0Sstevel@tonic-gateIn either case, the outgoing header will be formatted as: 4723*0Sstevel@tonic-gate 4724*0Sstevel@tonic-gate P3P: policyref="/w3c/p3p.xml" cp="CAO DSP LAW CURa" 4725*0Sstevel@tonic-gate 4726*0Sstevel@tonic-gate=head2 GENERATING A REDIRECTION HEADER 4727*0Sstevel@tonic-gate 4728*0Sstevel@tonic-gate print $query->redirect('http://somewhere.else/in/movie/land'); 4729*0Sstevel@tonic-gate 4730*0Sstevel@tonic-gateSometimes you don't want to produce a document yourself, but simply 4731*0Sstevel@tonic-gateredirect the browser elsewhere, perhaps choosing a URL based on the 4732*0Sstevel@tonic-gatetime of day or the identity of the user. 4733*0Sstevel@tonic-gate 4734*0Sstevel@tonic-gateThe redirect() function redirects the browser to a different URL. If 4735*0Sstevel@tonic-gateyou use redirection like this, you should B<not> print out a header as 4736*0Sstevel@tonic-gatewell. 4737*0Sstevel@tonic-gate 4738*0Sstevel@tonic-gateYou should always use full URLs (including the http: or ftp: part) in 4739*0Sstevel@tonic-gateredirection requests. Relative URLs will not work correctly. 4740*0Sstevel@tonic-gate 4741*0Sstevel@tonic-gateYou can also use named arguments: 4742*0Sstevel@tonic-gate 4743*0Sstevel@tonic-gate print $query->redirect(-uri=>'http://somewhere.else/in/movie/land', 4744*0Sstevel@tonic-gate -nph=>1); 4745*0Sstevel@tonic-gate 4746*0Sstevel@tonic-gateThe B<-nph> parameter, if set to a true value, will issue the correct 4747*0Sstevel@tonic-gateheaders to work with a NPH (no-parse-header) script. This is important 4748*0Sstevel@tonic-gateto use with certain servers, such as Microsoft IIS, which 4749*0Sstevel@tonic-gateexpect all their scripts to be NPH. 4750*0Sstevel@tonic-gate 4751*0Sstevel@tonic-gate=head2 CREATING THE HTML DOCUMENT HEADER 4752*0Sstevel@tonic-gate 4753*0Sstevel@tonic-gate print $query->start_html(-title=>'Secrets of the Pyramids', 4754*0Sstevel@tonic-gate -author=>'fred@capricorn.org', 4755*0Sstevel@tonic-gate -base=>'true', 4756*0Sstevel@tonic-gate -target=>'_blank', 4757*0Sstevel@tonic-gate -meta=>{'keywords'=>'pharaoh secret mummy', 4758*0Sstevel@tonic-gate 'copyright'=>'copyright 1996 King Tut'}, 4759*0Sstevel@tonic-gate -style=>{'src'=>'/styles/style1.css'}, 4760*0Sstevel@tonic-gate -BGCOLOR=>'blue'); 4761*0Sstevel@tonic-gate 4762*0Sstevel@tonic-gateAfter creating the HTTP header, most CGI scripts will start writing 4763*0Sstevel@tonic-gateout an HTML document. The start_html() routine creates the top of the 4764*0Sstevel@tonic-gatepage, along with a lot of optional information that controls the 4765*0Sstevel@tonic-gatepage's appearance and behavior. 4766*0Sstevel@tonic-gate 4767*0Sstevel@tonic-gateThis method returns a canned HTML header and the opening <body> tag. 4768*0Sstevel@tonic-gateAll parameters are optional. In the named parameter form, recognized 4769*0Sstevel@tonic-gateparameters are -title, -author, -base, -xbase, -dtd, -lang and -target 4770*0Sstevel@tonic-gate(see below for the explanation). Any additional parameters you 4771*0Sstevel@tonic-gateprovide, such as the Netscape unofficial BGCOLOR attribute, are added 4772*0Sstevel@tonic-gateto the <body> tag. Additional parameters must be proceeded by a 4773*0Sstevel@tonic-gatehyphen. 4774*0Sstevel@tonic-gate 4775*0Sstevel@tonic-gateThe argument B<-xbase> allows you to provide an HREF for the <base> tag 4776*0Sstevel@tonic-gatedifferent from the current location, as in 4777*0Sstevel@tonic-gate 4778*0Sstevel@tonic-gate -xbase=>"http://home.mcom.com/" 4779*0Sstevel@tonic-gate 4780*0Sstevel@tonic-gateAll relative links will be interpreted relative to this tag. 4781*0Sstevel@tonic-gate 4782*0Sstevel@tonic-gateThe argument B<-target> allows you to provide a default target frame 4783*0Sstevel@tonic-gatefor all the links and fill-out forms on the page. B<This is a 4784*0Sstevel@tonic-gatenon-standard HTTP feature which only works with Netscape browsers!> 4785*0Sstevel@tonic-gateSee the Netscape documentation on frames for details of how to 4786*0Sstevel@tonic-gatemanipulate this. 4787*0Sstevel@tonic-gate 4788*0Sstevel@tonic-gate -target=>"answer_window" 4789*0Sstevel@tonic-gate 4790*0Sstevel@tonic-gateAll relative links will be interpreted relative to this tag. 4791*0Sstevel@tonic-gateYou add arbitrary meta information to the header with the B<-meta> 4792*0Sstevel@tonic-gateargument. This argument expects a reference to an associative array 4793*0Sstevel@tonic-gatecontaining name/value pairs of meta information. These will be turned 4794*0Sstevel@tonic-gateinto a series of header <meta> tags that look something like this: 4795*0Sstevel@tonic-gate 4796*0Sstevel@tonic-gate <meta name="keywords" content="pharaoh secret mummy"> 4797*0Sstevel@tonic-gate <meta name="description" content="copyright 1996 King Tut"> 4798*0Sstevel@tonic-gate 4799*0Sstevel@tonic-gateTo create an HTTP-EQUIV type of <meta> tag, use B<-head>, described 4800*0Sstevel@tonic-gatebelow. 4801*0Sstevel@tonic-gate 4802*0Sstevel@tonic-gateThe B<-style> argument is used to incorporate cascading stylesheets 4803*0Sstevel@tonic-gateinto your code. See the section on CASCADING STYLESHEETS for more 4804*0Sstevel@tonic-gateinformation. 4805*0Sstevel@tonic-gate 4806*0Sstevel@tonic-gateThe B<-lang> argument is used to incorporate a language attribute into 4807*0Sstevel@tonic-gatethe <html> tag. The default if not specified is "en-US" for US 4808*0Sstevel@tonic-gateEnglish. For example: 4809*0Sstevel@tonic-gate 4810*0Sstevel@tonic-gate print $q->start_html(-lang=>'fr-CA'); 4811*0Sstevel@tonic-gate 4812*0Sstevel@tonic-gateTo leave off the lang attribute, as you must do if you want to generate 4813*0Sstevel@tonic-gatelegal HTML 3.2 or earlier, pass the empty string (-lang=>''). 4814*0Sstevel@tonic-gate 4815*0Sstevel@tonic-gateThe B<-encoding> argument can be used to specify the character set for 4816*0Sstevel@tonic-gateXHTML. It defaults to iso-8859-1 if not specified. 4817*0Sstevel@tonic-gate 4818*0Sstevel@tonic-gateYou can place other arbitrary HTML elements to the <head> section with the 4819*0Sstevel@tonic-gateB<-head> tag. For example, to place the rarely-used <link> element in the 4820*0Sstevel@tonic-gatehead section, use this: 4821*0Sstevel@tonic-gate 4822*0Sstevel@tonic-gate print start_html(-head=>Link({-rel=>'next', 4823*0Sstevel@tonic-gate -href=>'http://www.capricorn.com/s2.html'})); 4824*0Sstevel@tonic-gate 4825*0Sstevel@tonic-gateTo incorporate multiple HTML elements into the <head> section, just pass an 4826*0Sstevel@tonic-gatearray reference: 4827*0Sstevel@tonic-gate 4828*0Sstevel@tonic-gate print start_html(-head=>[ 4829*0Sstevel@tonic-gate Link({-rel=>'next', 4830*0Sstevel@tonic-gate -href=>'http://www.capricorn.com/s2.html'}), 4831*0Sstevel@tonic-gate Link({-rel=>'previous', 4832*0Sstevel@tonic-gate -href=>'http://www.capricorn.com/s1.html'}) 4833*0Sstevel@tonic-gate ] 4834*0Sstevel@tonic-gate ); 4835*0Sstevel@tonic-gate 4836*0Sstevel@tonic-gateAnd here's how to create an HTTP-EQUIV <meta> tag: 4837*0Sstevel@tonic-gate 4838*0Sstevel@tonic-gate print start_html(-head=>meta({-http_equiv => 'Content-Type', 4839*0Sstevel@tonic-gate -content => 'text/html'})) 4840*0Sstevel@tonic-gate 4841*0Sstevel@tonic-gate 4842*0Sstevel@tonic-gateJAVASCRIPTING: The B<-script>, B<-noScript>, B<-onLoad>, 4843*0Sstevel@tonic-gateB<-onMouseOver>, B<-onMouseOut> and B<-onUnload> parameters are used 4844*0Sstevel@tonic-gateto add Netscape JavaScript calls to your pages. B<-script> should 4845*0Sstevel@tonic-gatepoint to a block of text containing JavaScript function definitions. 4846*0Sstevel@tonic-gateThis block will be placed within a <script> block inside the HTML (not 4847*0Sstevel@tonic-gateHTTP) header. The block is placed in the header in order to give your 4848*0Sstevel@tonic-gatepage a fighting chance of having all its JavaScript functions in place 4849*0Sstevel@tonic-gateeven if the user presses the stop button before the page has loaded 4850*0Sstevel@tonic-gatecompletely. CGI.pm attempts to format the script in such a way that 4851*0Sstevel@tonic-gateJavaScript-naive browsers will not choke on the code: unfortunately 4852*0Sstevel@tonic-gatethere are some browsers, such as Chimera for Unix, that get confused 4853*0Sstevel@tonic-gateby it nevertheless. 4854*0Sstevel@tonic-gate 4855*0Sstevel@tonic-gateThe B<-onLoad> and B<-onUnload> parameters point to fragments of JavaScript 4856*0Sstevel@tonic-gatecode to execute when the page is respectively opened and closed by the 4857*0Sstevel@tonic-gatebrowser. Usually these parameters are calls to functions defined in the 4858*0Sstevel@tonic-gateB<-script> field: 4859*0Sstevel@tonic-gate 4860*0Sstevel@tonic-gate $query = new CGI; 4861*0Sstevel@tonic-gate print $query->header; 4862*0Sstevel@tonic-gate $JSCRIPT=<<END; 4863*0Sstevel@tonic-gate // Ask a silly question 4864*0Sstevel@tonic-gate function riddle_me_this() { 4865*0Sstevel@tonic-gate var r = prompt("What walks on four legs in the morning, " + 4866*0Sstevel@tonic-gate "two legs in the afternoon, " + 4867*0Sstevel@tonic-gate "and three legs in the evening?"); 4868*0Sstevel@tonic-gate response(r); 4869*0Sstevel@tonic-gate } 4870*0Sstevel@tonic-gate // Get a silly answer 4871*0Sstevel@tonic-gate function response(answer) { 4872*0Sstevel@tonic-gate if (answer == "man") 4873*0Sstevel@tonic-gate alert("Right you are!"); 4874*0Sstevel@tonic-gate else 4875*0Sstevel@tonic-gate alert("Wrong! Guess again."); 4876*0Sstevel@tonic-gate } 4877*0Sstevel@tonic-gate END 4878*0Sstevel@tonic-gate print $query->start_html(-title=>'The Riddle of the Sphinx', 4879*0Sstevel@tonic-gate -script=>$JSCRIPT); 4880*0Sstevel@tonic-gate 4881*0Sstevel@tonic-gateUse the B<-noScript> parameter to pass some HTML text that will be displayed on 4882*0Sstevel@tonic-gatebrowsers that do not have JavaScript (or browsers where JavaScript is turned 4883*0Sstevel@tonic-gateoff). 4884*0Sstevel@tonic-gate 4885*0Sstevel@tonic-gateNetscape 3.0 recognizes several attributes of the <script> tag, 4886*0Sstevel@tonic-gateincluding LANGUAGE and SRC. The latter is particularly interesting, 4887*0Sstevel@tonic-gateas it allows you to keep the JavaScript code in a file or CGI script 4888*0Sstevel@tonic-gaterather than cluttering up each page with the source. To use these 4889*0Sstevel@tonic-gateattributes pass a HASH reference in the B<-script> parameter containing 4890*0Sstevel@tonic-gateone or more of -language, -src, or -code: 4891*0Sstevel@tonic-gate 4892*0Sstevel@tonic-gate print $q->start_html(-title=>'The Riddle of the Sphinx', 4893*0Sstevel@tonic-gate -script=>{-language=>'JAVASCRIPT', 4894*0Sstevel@tonic-gate -src=>'/javascript/sphinx.js'} 4895*0Sstevel@tonic-gate ); 4896*0Sstevel@tonic-gate 4897*0Sstevel@tonic-gate print $q->(-title=>'The Riddle of the Sphinx', 4898*0Sstevel@tonic-gate -script=>{-language=>'PERLSCRIPT', 4899*0Sstevel@tonic-gate -code=>'print "hello world!\n;"'} 4900*0Sstevel@tonic-gate ); 4901*0Sstevel@tonic-gate 4902*0Sstevel@tonic-gate 4903*0Sstevel@tonic-gateA final feature allows you to incorporate multiple <script> sections into the 4904*0Sstevel@tonic-gateheader. Just pass the list of script sections as an array reference. 4905*0Sstevel@tonic-gatethis allows you to specify different source files for different dialects 4906*0Sstevel@tonic-gateof JavaScript. Example: 4907*0Sstevel@tonic-gate 4908*0Sstevel@tonic-gate print $q->start_html(-title=>'The Riddle of the Sphinx', 4909*0Sstevel@tonic-gate -script=>[ 4910*0Sstevel@tonic-gate { -language => 'JavaScript1.0', 4911*0Sstevel@tonic-gate -src => '/javascript/utilities10.js' 4912*0Sstevel@tonic-gate }, 4913*0Sstevel@tonic-gate { -language => 'JavaScript1.1', 4914*0Sstevel@tonic-gate -src => '/javascript/utilities11.js' 4915*0Sstevel@tonic-gate }, 4916*0Sstevel@tonic-gate { -language => 'JavaScript1.2', 4917*0Sstevel@tonic-gate -src => '/javascript/utilities12.js' 4918*0Sstevel@tonic-gate }, 4919*0Sstevel@tonic-gate { -language => 'JavaScript28.2', 4920*0Sstevel@tonic-gate -src => '/javascript/utilities219.js' 4921*0Sstevel@tonic-gate } 4922*0Sstevel@tonic-gate ] 4923*0Sstevel@tonic-gate ); 4924*0Sstevel@tonic-gate 4925*0Sstevel@tonic-gateIf this looks a bit extreme, take my advice and stick with straight CGI scripting. 4926*0Sstevel@tonic-gate 4927*0Sstevel@tonic-gateSee 4928*0Sstevel@tonic-gate 4929*0Sstevel@tonic-gate http://home.netscape.com/eng/mozilla/2.0/handbook/javascript/ 4930*0Sstevel@tonic-gate 4931*0Sstevel@tonic-gatefor more information about JavaScript. 4932*0Sstevel@tonic-gate 4933*0Sstevel@tonic-gateThe old-style positional parameters are as follows: 4934*0Sstevel@tonic-gate 4935*0Sstevel@tonic-gate=over 4 4936*0Sstevel@tonic-gate 4937*0Sstevel@tonic-gate=item B<Parameters:> 4938*0Sstevel@tonic-gate 4939*0Sstevel@tonic-gate=item 1. 4940*0Sstevel@tonic-gate 4941*0Sstevel@tonic-gateThe title 4942*0Sstevel@tonic-gate 4943*0Sstevel@tonic-gate=item 2. 4944*0Sstevel@tonic-gate 4945*0Sstevel@tonic-gateThe author's e-mail address (will create a <link rev="MADE"> tag if present 4946*0Sstevel@tonic-gate 4947*0Sstevel@tonic-gate=item 3. 4948*0Sstevel@tonic-gate 4949*0Sstevel@tonic-gateA 'true' flag if you want to include a <base> tag in the header. This 4950*0Sstevel@tonic-gatehelps resolve relative addresses to absolute ones when the document is moved, 4951*0Sstevel@tonic-gatebut makes the document hierarchy non-portable. Use with care! 4952*0Sstevel@tonic-gate 4953*0Sstevel@tonic-gate=item 4, 5, 6... 4954*0Sstevel@tonic-gate 4955*0Sstevel@tonic-gateAny other parameters you want to include in the <body> tag. This is a good 4956*0Sstevel@tonic-gateplace to put Netscape extensions, such as colors and wallpaper patterns. 4957*0Sstevel@tonic-gate 4958*0Sstevel@tonic-gate=back 4959*0Sstevel@tonic-gate 4960*0Sstevel@tonic-gate=head2 ENDING THE HTML DOCUMENT: 4961*0Sstevel@tonic-gate 4962*0Sstevel@tonic-gate print $query->end_html 4963*0Sstevel@tonic-gate 4964*0Sstevel@tonic-gateThis ends an HTML document by printing the </body></html> tags. 4965*0Sstevel@tonic-gate 4966*0Sstevel@tonic-gate=head2 CREATING A SELF-REFERENCING URL THAT PRESERVES STATE INFORMATION: 4967*0Sstevel@tonic-gate 4968*0Sstevel@tonic-gate $myself = $query->self_url; 4969*0Sstevel@tonic-gate print q(<a href="$myself">I'm talking to myself.</a>); 4970*0Sstevel@tonic-gate 4971*0Sstevel@tonic-gateself_url() will return a URL, that, when selected, will reinvoke 4972*0Sstevel@tonic-gatethis script with all its state information intact. This is most 4973*0Sstevel@tonic-gateuseful when you want to jump around within the document using 4974*0Sstevel@tonic-gateinternal anchors but you don't want to disrupt the current contents 4975*0Sstevel@tonic-gateof the form(s). Something like this will do the trick. 4976*0Sstevel@tonic-gate 4977*0Sstevel@tonic-gate $myself = $query->self_url; 4978*0Sstevel@tonic-gate print "<a href=\"$myself#table1\">See table 1</a>"; 4979*0Sstevel@tonic-gate print "<a href=\"$myself#table2\">See table 2</a>"; 4980*0Sstevel@tonic-gate print "<a href=\"$myself#yourself\">See for yourself</a>"; 4981*0Sstevel@tonic-gate 4982*0Sstevel@tonic-gateIf you want more control over what's returned, using the B<url()> 4983*0Sstevel@tonic-gatemethod instead. 4984*0Sstevel@tonic-gate 4985*0Sstevel@tonic-gateYou can also retrieve the unprocessed query string with query_string(): 4986*0Sstevel@tonic-gate 4987*0Sstevel@tonic-gate $the_string = $query->query_string; 4988*0Sstevel@tonic-gate 4989*0Sstevel@tonic-gate=head2 OBTAINING THE SCRIPT'S URL 4990*0Sstevel@tonic-gate 4991*0Sstevel@tonic-gate $full_url = $query->url(); 4992*0Sstevel@tonic-gate $full_url = $query->url(-full=>1); #alternative syntax 4993*0Sstevel@tonic-gate $relative_url = $query->url(-relative=>1); 4994*0Sstevel@tonic-gate $absolute_url = $query->url(-absolute=>1); 4995*0Sstevel@tonic-gate $url_with_path = $query->url(-path_info=>1); 4996*0Sstevel@tonic-gate $url_with_path_and_query = $query->url(-path_info=>1,-query=>1); 4997*0Sstevel@tonic-gate $netloc = $query->url(-base => 1); 4998*0Sstevel@tonic-gate 4999*0Sstevel@tonic-gateB<url()> returns the script's URL in a variety of formats. Called 5000*0Sstevel@tonic-gatewithout any arguments, it returns the full form of the URL, including 5001*0Sstevel@tonic-gatehost name and port number 5002*0Sstevel@tonic-gate 5003*0Sstevel@tonic-gate http://your.host.com/path/to/script.cgi 5004*0Sstevel@tonic-gate 5005*0Sstevel@tonic-gateYou can modify this format with the following named arguments: 5006*0Sstevel@tonic-gate 5007*0Sstevel@tonic-gate=over 4 5008*0Sstevel@tonic-gate 5009*0Sstevel@tonic-gate=item B<-absolute> 5010*0Sstevel@tonic-gate 5011*0Sstevel@tonic-gateIf true, produce an absolute URL, e.g. 5012*0Sstevel@tonic-gate 5013*0Sstevel@tonic-gate /path/to/script.cgi 5014*0Sstevel@tonic-gate 5015*0Sstevel@tonic-gate=item B<-relative> 5016*0Sstevel@tonic-gate 5017*0Sstevel@tonic-gateProduce a relative URL. This is useful if you want to reinvoke your 5018*0Sstevel@tonic-gatescript with different parameters. For example: 5019*0Sstevel@tonic-gate 5020*0Sstevel@tonic-gate script.cgi 5021*0Sstevel@tonic-gate 5022*0Sstevel@tonic-gate=item B<-full> 5023*0Sstevel@tonic-gate 5024*0Sstevel@tonic-gateProduce the full URL, exactly as if called without any arguments. 5025*0Sstevel@tonic-gateThis overrides the -relative and -absolute arguments. 5026*0Sstevel@tonic-gate 5027*0Sstevel@tonic-gate=item B<-path> (B<-path_info>) 5028*0Sstevel@tonic-gate 5029*0Sstevel@tonic-gateAppend the additional path information to the URL. This can be 5030*0Sstevel@tonic-gatecombined with B<-full>, B<-absolute> or B<-relative>. B<-path_info> 5031*0Sstevel@tonic-gateis provided as a synonym. 5032*0Sstevel@tonic-gate 5033*0Sstevel@tonic-gate=item B<-query> (B<-query_string>) 5034*0Sstevel@tonic-gate 5035*0Sstevel@tonic-gateAppend the query string to the URL. This can be combined with 5036*0Sstevel@tonic-gateB<-full>, B<-absolute> or B<-relative>. B<-query_string> is provided 5037*0Sstevel@tonic-gateas a synonym. 5038*0Sstevel@tonic-gate 5039*0Sstevel@tonic-gate=item B<-base> 5040*0Sstevel@tonic-gate 5041*0Sstevel@tonic-gateGenerate just the protocol and net location, as in http://www.foo.com:8000 5042*0Sstevel@tonic-gate 5043*0Sstevel@tonic-gate=back 5044*0Sstevel@tonic-gate 5045*0Sstevel@tonic-gate=head2 MIXING POST AND URL PARAMETERS 5046*0Sstevel@tonic-gate 5047*0Sstevel@tonic-gate $color = $query->url_param('color'); 5048*0Sstevel@tonic-gate 5049*0Sstevel@tonic-gateIt is possible for a script to receive CGI parameters in the URL as 5050*0Sstevel@tonic-gatewell as in the fill-out form by creating a form that POSTs to a URL 5051*0Sstevel@tonic-gatecontaining a query string (a "?" mark followed by arguments). The 5052*0Sstevel@tonic-gateB<param()> method will always return the contents of the POSTed 5053*0Sstevel@tonic-gatefill-out form, ignoring the URL's query string. To retrieve URL 5054*0Sstevel@tonic-gateparameters, call the B<url_param()> method. Use it in the same way as 5055*0Sstevel@tonic-gateB<param()>. The main difference is that it allows you to read the 5056*0Sstevel@tonic-gateparameters, but not set them. 5057*0Sstevel@tonic-gate 5058*0Sstevel@tonic-gate 5059*0Sstevel@tonic-gateUnder no circumstances will the contents of the URL query string 5060*0Sstevel@tonic-gateinterfere with similarly-named CGI parameters in POSTed forms. If you 5061*0Sstevel@tonic-gatetry to mix a URL query string with a form submitted with the GET 5062*0Sstevel@tonic-gatemethod, the results will not be what you expect. 5063*0Sstevel@tonic-gate 5064*0Sstevel@tonic-gate=head1 CREATING STANDARD HTML ELEMENTS: 5065*0Sstevel@tonic-gate 5066*0Sstevel@tonic-gateCGI.pm defines general HTML shortcut methods for most, if not all of 5067*0Sstevel@tonic-gatethe HTML 3 and HTML 4 tags. HTML shortcuts are named after a single 5068*0Sstevel@tonic-gateHTML element and return a fragment of HTML text that you can then 5069*0Sstevel@tonic-gateprint or manipulate as you like. Each shortcut returns a fragment of 5070*0Sstevel@tonic-gateHTML code that you can append to a string, save to a file, or, most 5071*0Sstevel@tonic-gatecommonly, print out so that it displays in the browser window. 5072*0Sstevel@tonic-gate 5073*0Sstevel@tonic-gateThis example shows how to use the HTML methods: 5074*0Sstevel@tonic-gate 5075*0Sstevel@tonic-gate $q = new CGI; 5076*0Sstevel@tonic-gate print $q->blockquote( 5077*0Sstevel@tonic-gate "Many years ago on the island of", 5078*0Sstevel@tonic-gate $q->a({href=>"http://crete.org/"},"Crete"), 5079*0Sstevel@tonic-gate "there lived a Minotaur named", 5080*0Sstevel@tonic-gate $q->strong("Fred."), 5081*0Sstevel@tonic-gate ), 5082*0Sstevel@tonic-gate $q->hr; 5083*0Sstevel@tonic-gate 5084*0Sstevel@tonic-gateThis results in the following HTML code (extra newlines have been 5085*0Sstevel@tonic-gateadded for readability): 5086*0Sstevel@tonic-gate 5087*0Sstevel@tonic-gate <blockquote> 5088*0Sstevel@tonic-gate Many years ago on the island of 5089*0Sstevel@tonic-gate <a href="http://crete.org/">Crete</a> there lived 5090*0Sstevel@tonic-gate a minotaur named <strong>Fred.</strong> 5091*0Sstevel@tonic-gate </blockquote> 5092*0Sstevel@tonic-gate <hr> 5093*0Sstevel@tonic-gate 5094*0Sstevel@tonic-gateIf you find the syntax for calling the HTML shortcuts awkward, you can 5095*0Sstevel@tonic-gateimport them into your namespace and dispense with the object syntax 5096*0Sstevel@tonic-gatecompletely (see the next section for more details): 5097*0Sstevel@tonic-gate 5098*0Sstevel@tonic-gate use CGI ':standard'; 5099*0Sstevel@tonic-gate print blockquote( 5100*0Sstevel@tonic-gate "Many years ago on the island of", 5101*0Sstevel@tonic-gate a({href=>"http://crete.org/"},"Crete"), 5102*0Sstevel@tonic-gate "there lived a minotaur named", 5103*0Sstevel@tonic-gate strong("Fred."), 5104*0Sstevel@tonic-gate ), 5105*0Sstevel@tonic-gate hr; 5106*0Sstevel@tonic-gate 5107*0Sstevel@tonic-gate=head2 PROVIDING ARGUMENTS TO HTML SHORTCUTS 5108*0Sstevel@tonic-gate 5109*0Sstevel@tonic-gateThe HTML methods will accept zero, one or multiple arguments. If you 5110*0Sstevel@tonic-gateprovide no arguments, you get a single tag: 5111*0Sstevel@tonic-gate 5112*0Sstevel@tonic-gate print hr; # <hr> 5113*0Sstevel@tonic-gate 5114*0Sstevel@tonic-gateIf you provide one or more string arguments, they are concatenated 5115*0Sstevel@tonic-gatetogether with spaces and placed between opening and closing tags: 5116*0Sstevel@tonic-gate 5117*0Sstevel@tonic-gate print h1("Chapter","1"); # <h1>Chapter 1</h1>" 5118*0Sstevel@tonic-gate 5119*0Sstevel@tonic-gateIf the first argument is an associative array reference, then the keys 5120*0Sstevel@tonic-gateand values of the associative array become the HTML tag's attributes: 5121*0Sstevel@tonic-gate 5122*0Sstevel@tonic-gate print a({-href=>'fred.html',-target=>'_new'}, 5123*0Sstevel@tonic-gate "Open a new frame"); 5124*0Sstevel@tonic-gate 5125*0Sstevel@tonic-gate <a href="fred.html",target="_new">Open a new frame</a> 5126*0Sstevel@tonic-gate 5127*0Sstevel@tonic-gateYou may dispense with the dashes in front of the attribute names if 5128*0Sstevel@tonic-gateyou prefer: 5129*0Sstevel@tonic-gate 5130*0Sstevel@tonic-gate print img {src=>'fred.gif',align=>'LEFT'}; 5131*0Sstevel@tonic-gate 5132*0Sstevel@tonic-gate <img align="LEFT" src="fred.gif"> 5133*0Sstevel@tonic-gate 5134*0Sstevel@tonic-gateSometimes an HTML tag attribute has no argument. For example, ordered 5135*0Sstevel@tonic-gatelists can be marked as COMPACT. The syntax for this is an argument that 5136*0Sstevel@tonic-gatethat points to an undef string: 5137*0Sstevel@tonic-gate 5138*0Sstevel@tonic-gate print ol({compact=>undef},li('one'),li('two'),li('three')); 5139*0Sstevel@tonic-gate 5140*0Sstevel@tonic-gatePrior to CGI.pm version 2.41, providing an empty ('') string as an 5141*0Sstevel@tonic-gateattribute argument was the same as providing undef. However, this has 5142*0Sstevel@tonic-gatechanged in order to accommodate those who want to create tags of the form 5143*0Sstevel@tonic-gate<img alt="">. The difference is shown in these two pieces of code: 5144*0Sstevel@tonic-gate 5145*0Sstevel@tonic-gate CODE RESULT 5146*0Sstevel@tonic-gate img({alt=>undef}) <img alt> 5147*0Sstevel@tonic-gate img({alt=>''}) <img alt=""> 5148*0Sstevel@tonic-gate 5149*0Sstevel@tonic-gate=head2 THE DISTRIBUTIVE PROPERTY OF HTML SHORTCUTS 5150*0Sstevel@tonic-gate 5151*0Sstevel@tonic-gateOne of the cool features of the HTML shortcuts is that they are 5152*0Sstevel@tonic-gatedistributive. If you give them an argument consisting of a 5153*0Sstevel@tonic-gateB<reference> to a list, the tag will be distributed across each 5154*0Sstevel@tonic-gateelement of the list. For example, here's one way to make an ordered 5155*0Sstevel@tonic-gatelist: 5156*0Sstevel@tonic-gate 5157*0Sstevel@tonic-gate print ul( 5158*0Sstevel@tonic-gate li({-type=>'disc'},['Sneezy','Doc','Sleepy','Happy']) 5159*0Sstevel@tonic-gate ); 5160*0Sstevel@tonic-gate 5161*0Sstevel@tonic-gateThis example will result in HTML output that looks like this: 5162*0Sstevel@tonic-gate 5163*0Sstevel@tonic-gate <ul> 5164*0Sstevel@tonic-gate <li type="disc">Sneezy</li> 5165*0Sstevel@tonic-gate <li type="disc">Doc</li> 5166*0Sstevel@tonic-gate <li type="disc">Sleepy</li> 5167*0Sstevel@tonic-gate <li type="disc">Happy</li> 5168*0Sstevel@tonic-gate </ul> 5169*0Sstevel@tonic-gate 5170*0Sstevel@tonic-gateThis is extremely useful for creating tables. For example: 5171*0Sstevel@tonic-gate 5172*0Sstevel@tonic-gate print table({-border=>undef}, 5173*0Sstevel@tonic-gate caption('When Should You Eat Your Vegetables?'), 5174*0Sstevel@tonic-gate Tr({-align=>CENTER,-valign=>TOP}, 5175*0Sstevel@tonic-gate [ 5176*0Sstevel@tonic-gate th(['Vegetable', 'Breakfast','Lunch','Dinner']), 5177*0Sstevel@tonic-gate td(['Tomatoes' , 'no', 'yes', 'yes']), 5178*0Sstevel@tonic-gate td(['Broccoli' , 'no', 'no', 'yes']), 5179*0Sstevel@tonic-gate td(['Onions' , 'yes','yes', 'yes']) 5180*0Sstevel@tonic-gate ] 5181*0Sstevel@tonic-gate ) 5182*0Sstevel@tonic-gate ); 5183*0Sstevel@tonic-gate 5184*0Sstevel@tonic-gate=head2 HTML SHORTCUTS AND LIST INTERPOLATION 5185*0Sstevel@tonic-gate 5186*0Sstevel@tonic-gateConsider this bit of code: 5187*0Sstevel@tonic-gate 5188*0Sstevel@tonic-gate print blockquote(em('Hi'),'mom!')); 5189*0Sstevel@tonic-gate 5190*0Sstevel@tonic-gateIt will ordinarily return the string that you probably expect, namely: 5191*0Sstevel@tonic-gate 5192*0Sstevel@tonic-gate <blockquote><em>Hi</em> mom!</blockquote> 5193*0Sstevel@tonic-gate 5194*0Sstevel@tonic-gateNote the space between the element "Hi" and the element "mom!". 5195*0Sstevel@tonic-gateCGI.pm puts the extra space there using array interpolation, which is 5196*0Sstevel@tonic-gatecontrolled by the magic $" variable. Sometimes this extra space is 5197*0Sstevel@tonic-gatenot what you want, for example, when you are trying to align a series 5198*0Sstevel@tonic-gateof images. In this case, you can simply change the value of $" to an 5199*0Sstevel@tonic-gateempty string. 5200*0Sstevel@tonic-gate 5201*0Sstevel@tonic-gate { 5202*0Sstevel@tonic-gate local($") = ''; 5203*0Sstevel@tonic-gate print blockquote(em('Hi'),'mom!')); 5204*0Sstevel@tonic-gate } 5205*0Sstevel@tonic-gate 5206*0Sstevel@tonic-gateI suggest you put the code in a block as shown here. Otherwise the 5207*0Sstevel@tonic-gatechange to $" will affect all subsequent code until you explicitly 5208*0Sstevel@tonic-gatereset it. 5209*0Sstevel@tonic-gate 5210*0Sstevel@tonic-gate=head2 NON-STANDARD HTML SHORTCUTS 5211*0Sstevel@tonic-gate 5212*0Sstevel@tonic-gateA few HTML tags don't follow the standard pattern for various 5213*0Sstevel@tonic-gatereasons. 5214*0Sstevel@tonic-gate 5215*0Sstevel@tonic-gateB<comment()> generates an HTML comment (<!-- comment -->). Call it 5216*0Sstevel@tonic-gatelike 5217*0Sstevel@tonic-gate 5218*0Sstevel@tonic-gate print comment('here is my comment'); 5219*0Sstevel@tonic-gate 5220*0Sstevel@tonic-gateBecause of conflicts with built-in Perl functions, the following functions 5221*0Sstevel@tonic-gatebegin with initial caps: 5222*0Sstevel@tonic-gate 5223*0Sstevel@tonic-gate Select 5224*0Sstevel@tonic-gate Tr 5225*0Sstevel@tonic-gate Link 5226*0Sstevel@tonic-gate Delete 5227*0Sstevel@tonic-gate Accept 5228*0Sstevel@tonic-gate Sub 5229*0Sstevel@tonic-gate 5230*0Sstevel@tonic-gateIn addition, start_html(), end_html(), start_form(), end_form(), 5231*0Sstevel@tonic-gatestart_multipart_form() and all the fill-out form tags are special. 5232*0Sstevel@tonic-gateSee their respective sections. 5233*0Sstevel@tonic-gate 5234*0Sstevel@tonic-gate=head2 AUTOESCAPING HTML 5235*0Sstevel@tonic-gate 5236*0Sstevel@tonic-gateBy default, all HTML that is emitted by the form-generating functions 5237*0Sstevel@tonic-gateis passed through a function called escapeHTML(): 5238*0Sstevel@tonic-gate 5239*0Sstevel@tonic-gate=over 4 5240*0Sstevel@tonic-gate 5241*0Sstevel@tonic-gate=item $escaped_string = escapeHTML("unescaped string"); 5242*0Sstevel@tonic-gate 5243*0Sstevel@tonic-gateEscape HTML formatting characters in a string. 5244*0Sstevel@tonic-gate 5245*0Sstevel@tonic-gate=back 5246*0Sstevel@tonic-gate 5247*0Sstevel@tonic-gateProvided that you have specified a character set of ISO-8859-1 (the 5248*0Sstevel@tonic-gatedefault), the standard HTML escaping rules will be used. The "<" 5249*0Sstevel@tonic-gatecharacter becomes "<", ">" becomes ">", "&" becomes "&", and 5250*0Sstevel@tonic-gatethe quote character becomes """. In addition, the hexadecimal 5251*0Sstevel@tonic-gate0x8b and 0x9b characters, which some browsers incorrectly interpret 5252*0Sstevel@tonic-gateas the left and right angle-bracket characters, are replaced by their 5253*0Sstevel@tonic-gatenumeric character entities ("‹" and "›"). If you manually change 5254*0Sstevel@tonic-gatethe charset, either by calling the charset() method explicitly or by 5255*0Sstevel@tonic-gatepassing a -charset argument to header(), then B<all> characters will 5256*0Sstevel@tonic-gatebe replaced by their numeric entities, since CGI.pm has no lookup 5257*0Sstevel@tonic-gatetable for all the possible encodings. 5258*0Sstevel@tonic-gate 5259*0Sstevel@tonic-gateThe automatic escaping does not apply to other shortcuts, such as 5260*0Sstevel@tonic-gateh1(). You should call escapeHTML() yourself on untrusted data in 5261*0Sstevel@tonic-gateorder to protect your pages against nasty tricks that people may enter 5262*0Sstevel@tonic-gateinto guestbooks, etc.. To change the character set, use charset(). 5263*0Sstevel@tonic-gateTo turn autoescaping off completely, use autoEscape(0): 5264*0Sstevel@tonic-gate 5265*0Sstevel@tonic-gate=over 4 5266*0Sstevel@tonic-gate 5267*0Sstevel@tonic-gate=item $charset = charset([$charset]); 5268*0Sstevel@tonic-gate 5269*0Sstevel@tonic-gateGet or set the current character set. 5270*0Sstevel@tonic-gate 5271*0Sstevel@tonic-gate=item $flag = autoEscape([$flag]); 5272*0Sstevel@tonic-gate 5273*0Sstevel@tonic-gateGet or set the value of the autoescape flag. 5274*0Sstevel@tonic-gate 5275*0Sstevel@tonic-gate=back 5276*0Sstevel@tonic-gate 5277*0Sstevel@tonic-gate=head2 PRETTY-PRINTING HTML 5278*0Sstevel@tonic-gate 5279*0Sstevel@tonic-gateBy default, all the HTML produced by these functions comes out as one 5280*0Sstevel@tonic-gatelong line without carriage returns or indentation. This is yuck, but 5281*0Sstevel@tonic-gateit does reduce the size of the documents by 10-20%. To get 5282*0Sstevel@tonic-gatepretty-printed output, please use L<CGI::Pretty>, a subclass 5283*0Sstevel@tonic-gatecontributed by Brian Paulsen. 5284*0Sstevel@tonic-gate 5285*0Sstevel@tonic-gate=head1 CREATING FILL-OUT FORMS: 5286*0Sstevel@tonic-gate 5287*0Sstevel@tonic-gateI<General note> The various form-creating methods all return strings 5288*0Sstevel@tonic-gateto the caller, containing the tag or tags that will create the requested 5289*0Sstevel@tonic-gateform element. You are responsible for actually printing out these strings. 5290*0Sstevel@tonic-gateIt's set up this way so that you can place formatting tags 5291*0Sstevel@tonic-gatearound the form elements. 5292*0Sstevel@tonic-gate 5293*0Sstevel@tonic-gateI<Another note> The default values that you specify for the forms are only 5294*0Sstevel@tonic-gateused the B<first> time the script is invoked (when there is no query 5295*0Sstevel@tonic-gatestring). On subsequent invocations of the script (when there is a query 5296*0Sstevel@tonic-gatestring), the former values are used even if they are blank. 5297*0Sstevel@tonic-gate 5298*0Sstevel@tonic-gateIf you want to change the value of a field from its previous value, you have two 5299*0Sstevel@tonic-gatechoices: 5300*0Sstevel@tonic-gate 5301*0Sstevel@tonic-gate(1) call the param() method to set it. 5302*0Sstevel@tonic-gate 5303*0Sstevel@tonic-gate(2) use the -override (alias -force) parameter (a new feature in version 2.15). 5304*0Sstevel@tonic-gateThis forces the default value to be used, regardless of the previous value: 5305*0Sstevel@tonic-gate 5306*0Sstevel@tonic-gate print $query->textfield(-name=>'field_name', 5307*0Sstevel@tonic-gate -default=>'starting value', 5308*0Sstevel@tonic-gate -override=>1, 5309*0Sstevel@tonic-gate -size=>50, 5310*0Sstevel@tonic-gate -maxlength=>80); 5311*0Sstevel@tonic-gate 5312*0Sstevel@tonic-gateI<Yet another note> By default, the text and labels of form elements are 5313*0Sstevel@tonic-gateescaped according to HTML rules. This means that you can safely use 5314*0Sstevel@tonic-gate"<CLICK ME>" as the label for a button. However, it also interferes with 5315*0Sstevel@tonic-gateyour ability to incorporate special HTML character sequences, such as Á, 5316*0Sstevel@tonic-gateinto your fields. If you wish to turn off automatic escaping, call the 5317*0Sstevel@tonic-gateautoEscape() method with a false value immediately after creating the CGI object: 5318*0Sstevel@tonic-gate 5319*0Sstevel@tonic-gate $query = new CGI; 5320*0Sstevel@tonic-gate $query->autoEscape(undef); 5321*0Sstevel@tonic-gate 5322*0Sstevel@tonic-gate=head2 CREATING AN ISINDEX TAG 5323*0Sstevel@tonic-gate 5324*0Sstevel@tonic-gate print $query->isindex(-action=>$action); 5325*0Sstevel@tonic-gate 5326*0Sstevel@tonic-gate -or- 5327*0Sstevel@tonic-gate 5328*0Sstevel@tonic-gate print $query->isindex($action); 5329*0Sstevel@tonic-gate 5330*0Sstevel@tonic-gatePrints out an <isindex> tag. Not very exciting. The parameter 5331*0Sstevel@tonic-gate-action specifies the URL of the script to process the query. The 5332*0Sstevel@tonic-gatedefault is to process the query with the current script. 5333*0Sstevel@tonic-gate 5334*0Sstevel@tonic-gate=head2 STARTING AND ENDING A FORM 5335*0Sstevel@tonic-gate 5336*0Sstevel@tonic-gate print $query->start_form(-method=>$method, 5337*0Sstevel@tonic-gate -action=>$action, 5338*0Sstevel@tonic-gate -enctype=>$encoding); 5339*0Sstevel@tonic-gate <... various form stuff ...> 5340*0Sstevel@tonic-gate print $query->endform; 5341*0Sstevel@tonic-gate 5342*0Sstevel@tonic-gate -or- 5343*0Sstevel@tonic-gate 5344*0Sstevel@tonic-gate print $query->start_form($method,$action,$encoding); 5345*0Sstevel@tonic-gate <... various form stuff ...> 5346*0Sstevel@tonic-gate print $query->endform; 5347*0Sstevel@tonic-gate 5348*0Sstevel@tonic-gatestart_form() will return a <form> tag with the optional method, 5349*0Sstevel@tonic-gateaction and form encoding that you specify. The defaults are: 5350*0Sstevel@tonic-gate 5351*0Sstevel@tonic-gate method: POST 5352*0Sstevel@tonic-gate action: this script 5353*0Sstevel@tonic-gate enctype: application/x-www-form-urlencoded 5354*0Sstevel@tonic-gate 5355*0Sstevel@tonic-gateendform() returns the closing </form> tag. 5356*0Sstevel@tonic-gate 5357*0Sstevel@tonic-gateStart_form()'s enctype argument tells the browser how to package the various 5358*0Sstevel@tonic-gatefields of the form before sending the form to the server. Two 5359*0Sstevel@tonic-gatevalues are possible: 5360*0Sstevel@tonic-gate 5361*0Sstevel@tonic-gateB<Note:> This method was previously named startform(), and startform() 5362*0Sstevel@tonic-gateis still recognized as an alias. 5363*0Sstevel@tonic-gate 5364*0Sstevel@tonic-gate=over 4 5365*0Sstevel@tonic-gate 5366*0Sstevel@tonic-gate=item B<application/x-www-form-urlencoded> 5367*0Sstevel@tonic-gate 5368*0Sstevel@tonic-gateThis is the older type of encoding used by all browsers prior to 5369*0Sstevel@tonic-gateNetscape 2.0. It is compatible with many CGI scripts and is 5370*0Sstevel@tonic-gatesuitable for short fields containing text data. For your 5371*0Sstevel@tonic-gateconvenience, CGI.pm stores the name of this encoding 5372*0Sstevel@tonic-gatetype in B<&CGI::URL_ENCODED>. 5373*0Sstevel@tonic-gate 5374*0Sstevel@tonic-gate=item B<multipart/form-data> 5375*0Sstevel@tonic-gate 5376*0Sstevel@tonic-gateThis is the newer type of encoding introduced by Netscape 2.0. 5377*0Sstevel@tonic-gateIt is suitable for forms that contain very large fields or that 5378*0Sstevel@tonic-gateare intended for transferring binary data. Most importantly, 5379*0Sstevel@tonic-gateit enables the "file upload" feature of Netscape 2.0 forms. For 5380*0Sstevel@tonic-gateyour convenience, CGI.pm stores the name of this encoding type 5381*0Sstevel@tonic-gatein B<&CGI::MULTIPART> 5382*0Sstevel@tonic-gate 5383*0Sstevel@tonic-gateForms that use this type of encoding are not easily interpreted 5384*0Sstevel@tonic-gateby CGI scripts unless they use CGI.pm or another library designed 5385*0Sstevel@tonic-gateto handle them. 5386*0Sstevel@tonic-gate 5387*0Sstevel@tonic-gate=back 5388*0Sstevel@tonic-gate 5389*0Sstevel@tonic-gateFor compatibility, the start_form() method uses the older form of 5390*0Sstevel@tonic-gateencoding by default. If you want to use the newer form of encoding 5391*0Sstevel@tonic-gateby default, you can call B<start_multipart_form()> instead of 5392*0Sstevel@tonic-gateB<start_form()>. 5393*0Sstevel@tonic-gate 5394*0Sstevel@tonic-gateJAVASCRIPTING: The B<-name> and B<-onSubmit> parameters are provided 5395*0Sstevel@tonic-gatefor use with JavaScript. The -name parameter gives the 5396*0Sstevel@tonic-gateform a name so that it can be identified and manipulated by 5397*0Sstevel@tonic-gateJavaScript functions. -onSubmit should point to a JavaScript 5398*0Sstevel@tonic-gatefunction that will be executed just before the form is submitted to your 5399*0Sstevel@tonic-gateserver. You can use this opportunity to check the contents of the form 5400*0Sstevel@tonic-gatefor consistency and completeness. If you find something wrong, you 5401*0Sstevel@tonic-gatecan put up an alert box or maybe fix things up yourself. You can 5402*0Sstevel@tonic-gateabort the submission by returning false from this function. 5403*0Sstevel@tonic-gate 5404*0Sstevel@tonic-gateUsually the bulk of JavaScript functions are defined in a <script> 5405*0Sstevel@tonic-gateblock in the HTML header and -onSubmit points to one of these function 5406*0Sstevel@tonic-gatecall. See start_html() for details. 5407*0Sstevel@tonic-gate 5408*0Sstevel@tonic-gate=head2 CREATING A TEXT FIELD 5409*0Sstevel@tonic-gate 5410*0Sstevel@tonic-gate print $query->textfield(-name=>'field_name', 5411*0Sstevel@tonic-gate -default=>'starting value', 5412*0Sstevel@tonic-gate -size=>50, 5413*0Sstevel@tonic-gate -maxlength=>80); 5414*0Sstevel@tonic-gate -or- 5415*0Sstevel@tonic-gate 5416*0Sstevel@tonic-gate print $query->textfield('field_name','starting value',50,80); 5417*0Sstevel@tonic-gate 5418*0Sstevel@tonic-gatetextfield() will return a text input field. 5419*0Sstevel@tonic-gate 5420*0Sstevel@tonic-gate=over 4 5421*0Sstevel@tonic-gate 5422*0Sstevel@tonic-gate=item B<Parameters> 5423*0Sstevel@tonic-gate 5424*0Sstevel@tonic-gate=item 1. 5425*0Sstevel@tonic-gate 5426*0Sstevel@tonic-gateThe first parameter is the required name for the field (-name). 5427*0Sstevel@tonic-gate 5428*0Sstevel@tonic-gate=item 2. 5429*0Sstevel@tonic-gate 5430*0Sstevel@tonic-gateThe optional second parameter is the default starting value for the field 5431*0Sstevel@tonic-gatecontents (-default). 5432*0Sstevel@tonic-gate 5433*0Sstevel@tonic-gate=item 3. 5434*0Sstevel@tonic-gate 5435*0Sstevel@tonic-gateThe optional third parameter is the size of the field in 5436*0Sstevel@tonic-gate characters (-size). 5437*0Sstevel@tonic-gate 5438*0Sstevel@tonic-gate=item 4. 5439*0Sstevel@tonic-gate 5440*0Sstevel@tonic-gateThe optional fourth parameter is the maximum number of characters the 5441*0Sstevel@tonic-gate field will accept (-maxlength). 5442*0Sstevel@tonic-gate 5443*0Sstevel@tonic-gate=back 5444*0Sstevel@tonic-gate 5445*0Sstevel@tonic-gateAs with all these methods, the field will be initialized with its 5446*0Sstevel@tonic-gateprevious contents from earlier invocations of the script. 5447*0Sstevel@tonic-gateWhen the form is processed, the value of the text field can be 5448*0Sstevel@tonic-gateretrieved with: 5449*0Sstevel@tonic-gate 5450*0Sstevel@tonic-gate $value = $query->param('foo'); 5451*0Sstevel@tonic-gate 5452*0Sstevel@tonic-gateIf you want to reset it from its initial value after the script has been 5453*0Sstevel@tonic-gatecalled once, you can do so like this: 5454*0Sstevel@tonic-gate 5455*0Sstevel@tonic-gate $query->param('foo',"I'm taking over this value!"); 5456*0Sstevel@tonic-gate 5457*0Sstevel@tonic-gateNEW AS OF VERSION 2.15: If you don't want the field to take on its previous 5458*0Sstevel@tonic-gatevalue, you can force its current value by using the -override (alias -force) 5459*0Sstevel@tonic-gateparameter: 5460*0Sstevel@tonic-gate 5461*0Sstevel@tonic-gate print $query->textfield(-name=>'field_name', 5462*0Sstevel@tonic-gate -default=>'starting value', 5463*0Sstevel@tonic-gate -override=>1, 5464*0Sstevel@tonic-gate -size=>50, 5465*0Sstevel@tonic-gate -maxlength=>80); 5466*0Sstevel@tonic-gate 5467*0Sstevel@tonic-gateJAVASCRIPTING: You can also provide B<-onChange>, B<-onFocus>, 5468*0Sstevel@tonic-gateB<-onBlur>, B<-onMouseOver>, B<-onMouseOut> and B<-onSelect> 5469*0Sstevel@tonic-gateparameters to register JavaScript event handlers. The onChange 5470*0Sstevel@tonic-gatehandler will be called whenever the user changes the contents of the 5471*0Sstevel@tonic-gatetext field. You can do text validation if you like. onFocus and 5472*0Sstevel@tonic-gateonBlur are called respectively when the insertion point moves into and 5473*0Sstevel@tonic-gateout of the text field. onSelect is called when the user changes the 5474*0Sstevel@tonic-gateportion of the text that is selected. 5475*0Sstevel@tonic-gate 5476*0Sstevel@tonic-gate=head2 CREATING A BIG TEXT FIELD 5477*0Sstevel@tonic-gate 5478*0Sstevel@tonic-gate print $query->textarea(-name=>'foo', 5479*0Sstevel@tonic-gate -default=>'starting value', 5480*0Sstevel@tonic-gate -rows=>10, 5481*0Sstevel@tonic-gate -columns=>50); 5482*0Sstevel@tonic-gate 5483*0Sstevel@tonic-gate -or 5484*0Sstevel@tonic-gate 5485*0Sstevel@tonic-gate print $query->textarea('foo','starting value',10,50); 5486*0Sstevel@tonic-gate 5487*0Sstevel@tonic-gatetextarea() is just like textfield, but it allows you to specify 5488*0Sstevel@tonic-gaterows and columns for a multiline text entry box. You can provide 5489*0Sstevel@tonic-gatea starting value for the field, which can be long and contain 5490*0Sstevel@tonic-gatemultiple lines. 5491*0Sstevel@tonic-gate 5492*0Sstevel@tonic-gateJAVASCRIPTING: The B<-onChange>, B<-onFocus>, B<-onBlur> , 5493*0Sstevel@tonic-gateB<-onMouseOver>, B<-onMouseOut>, and B<-onSelect> parameters are 5494*0Sstevel@tonic-gaterecognized. See textfield(). 5495*0Sstevel@tonic-gate 5496*0Sstevel@tonic-gate=head2 CREATING A PASSWORD FIELD 5497*0Sstevel@tonic-gate 5498*0Sstevel@tonic-gate print $query->password_field(-name=>'secret', 5499*0Sstevel@tonic-gate -value=>'starting value', 5500*0Sstevel@tonic-gate -size=>50, 5501*0Sstevel@tonic-gate -maxlength=>80); 5502*0Sstevel@tonic-gate -or- 5503*0Sstevel@tonic-gate 5504*0Sstevel@tonic-gate print $query->password_field('secret','starting value',50,80); 5505*0Sstevel@tonic-gate 5506*0Sstevel@tonic-gatepassword_field() is identical to textfield(), except that its contents 5507*0Sstevel@tonic-gatewill be starred out on the web page. 5508*0Sstevel@tonic-gate 5509*0Sstevel@tonic-gateJAVASCRIPTING: The B<-onChange>, B<-onFocus>, B<-onBlur>, 5510*0Sstevel@tonic-gateB<-onMouseOver>, B<-onMouseOut> and B<-onSelect> parameters are 5511*0Sstevel@tonic-gaterecognized. See textfield(). 5512*0Sstevel@tonic-gate 5513*0Sstevel@tonic-gate=head2 CREATING A FILE UPLOAD FIELD 5514*0Sstevel@tonic-gate 5515*0Sstevel@tonic-gate print $query->filefield(-name=>'uploaded_file', 5516*0Sstevel@tonic-gate -default=>'starting value', 5517*0Sstevel@tonic-gate -size=>50, 5518*0Sstevel@tonic-gate -maxlength=>80); 5519*0Sstevel@tonic-gate -or- 5520*0Sstevel@tonic-gate 5521*0Sstevel@tonic-gate print $query->filefield('uploaded_file','starting value',50,80); 5522*0Sstevel@tonic-gate 5523*0Sstevel@tonic-gatefilefield() will return a file upload field for Netscape 2.0 browsers. 5524*0Sstevel@tonic-gateIn order to take full advantage of this I<you must use the new 5525*0Sstevel@tonic-gatemultipart encoding scheme> for the form. You can do this either 5526*0Sstevel@tonic-gateby calling B<start_form()> with an encoding type of B<&CGI::MULTIPART>, 5527*0Sstevel@tonic-gateor by calling the new method B<start_multipart_form()> instead of 5528*0Sstevel@tonic-gatevanilla B<start_form()>. 5529*0Sstevel@tonic-gate 5530*0Sstevel@tonic-gate=over 4 5531*0Sstevel@tonic-gate 5532*0Sstevel@tonic-gate=item B<Parameters> 5533*0Sstevel@tonic-gate 5534*0Sstevel@tonic-gate=item 1. 5535*0Sstevel@tonic-gate 5536*0Sstevel@tonic-gateThe first parameter is the required name for the field (-name). 5537*0Sstevel@tonic-gate 5538*0Sstevel@tonic-gate=item 2. 5539*0Sstevel@tonic-gate 5540*0Sstevel@tonic-gateThe optional second parameter is the starting value for the field contents 5541*0Sstevel@tonic-gateto be used as the default file name (-default). 5542*0Sstevel@tonic-gate 5543*0Sstevel@tonic-gateFor security reasons, browsers don't pay any attention to this field, 5544*0Sstevel@tonic-gateand so the starting value will always be blank. Worse, the field 5545*0Sstevel@tonic-gateloses its "sticky" behavior and forgets its previous contents. The 5546*0Sstevel@tonic-gatestarting value field is called for in the HTML specification, however, 5547*0Sstevel@tonic-gateand possibly some browser will eventually provide support for it. 5548*0Sstevel@tonic-gate 5549*0Sstevel@tonic-gate=item 3. 5550*0Sstevel@tonic-gate 5551*0Sstevel@tonic-gateThe optional third parameter is the size of the field in 5552*0Sstevel@tonic-gatecharacters (-size). 5553*0Sstevel@tonic-gate 5554*0Sstevel@tonic-gate=item 4. 5555*0Sstevel@tonic-gate 5556*0Sstevel@tonic-gateThe optional fourth parameter is the maximum number of characters the 5557*0Sstevel@tonic-gatefield will accept (-maxlength). 5558*0Sstevel@tonic-gate 5559*0Sstevel@tonic-gate=back 5560*0Sstevel@tonic-gate 5561*0Sstevel@tonic-gateWhen the form is processed, you can retrieve the entered filename 5562*0Sstevel@tonic-gateby calling param(): 5563*0Sstevel@tonic-gate 5564*0Sstevel@tonic-gate $filename = $query->param('uploaded_file'); 5565*0Sstevel@tonic-gate 5566*0Sstevel@tonic-gateDifferent browsers will return slightly different things for the 5567*0Sstevel@tonic-gatename. Some browsers return the filename only. Others return the full 5568*0Sstevel@tonic-gatepath to the file, using the path conventions of the user's machine. 5569*0Sstevel@tonic-gateRegardless, the name returned is always the name of the file on the 5570*0Sstevel@tonic-gateI<user's> machine, and is unrelated to the name of the temporary file 5571*0Sstevel@tonic-gatethat CGI.pm creates during upload spooling (see below). 5572*0Sstevel@tonic-gate 5573*0Sstevel@tonic-gateThe filename returned is also a file handle. You can read the contents 5574*0Sstevel@tonic-gateof the file using standard Perl file reading calls: 5575*0Sstevel@tonic-gate 5576*0Sstevel@tonic-gate # Read a text file and print it out 5577*0Sstevel@tonic-gate while (<$filename>) { 5578*0Sstevel@tonic-gate print; 5579*0Sstevel@tonic-gate } 5580*0Sstevel@tonic-gate 5581*0Sstevel@tonic-gate # Copy a binary file to somewhere safe 5582*0Sstevel@tonic-gate open (OUTFILE,">>/usr/local/web/users/feedback"); 5583*0Sstevel@tonic-gate while ($bytesread=read($filename,$buffer,1024)) { 5584*0Sstevel@tonic-gate print OUTFILE $buffer; 5585*0Sstevel@tonic-gate } 5586*0Sstevel@tonic-gate 5587*0Sstevel@tonic-gateHowever, there are problems with the dual nature of the upload fields. 5588*0Sstevel@tonic-gateIf you C<use strict>, then Perl will complain when you try to use a 5589*0Sstevel@tonic-gatestring as a filehandle. You can get around this by placing the file 5590*0Sstevel@tonic-gatereading code in a block containing the C<no strict> pragma. More 5591*0Sstevel@tonic-gateseriously, it is possible for the remote user to type garbage into the 5592*0Sstevel@tonic-gateupload field, in which case what you get from param() is not a 5593*0Sstevel@tonic-gatefilehandle at all, but a string. 5594*0Sstevel@tonic-gate 5595*0Sstevel@tonic-gateTo be safe, use the I<upload()> function (new in version 2.47). When 5596*0Sstevel@tonic-gatecalled with the name of an upload field, I<upload()> returns a 5597*0Sstevel@tonic-gatefilehandle, or undef if the parameter is not a valid filehandle. 5598*0Sstevel@tonic-gate 5599*0Sstevel@tonic-gate $fh = $query->upload('uploaded_file'); 5600*0Sstevel@tonic-gate while (<$fh>) { 5601*0Sstevel@tonic-gate print; 5602*0Sstevel@tonic-gate } 5603*0Sstevel@tonic-gate 5604*0Sstevel@tonic-gateIn an array context, upload() will return an array of filehandles. 5605*0Sstevel@tonic-gateThis makes it possible to create forms that use the same name for 5606*0Sstevel@tonic-gatemultiple upload fields. 5607*0Sstevel@tonic-gate 5608*0Sstevel@tonic-gateThis is the recommended idiom. 5609*0Sstevel@tonic-gate 5610*0Sstevel@tonic-gateWhen a file is uploaded the browser usually sends along some 5611*0Sstevel@tonic-gateinformation along with it in the format of headers. The information 5612*0Sstevel@tonic-gateusually includes the MIME content type. Future browsers may send 5613*0Sstevel@tonic-gateother information as well (such as modification date and size). To 5614*0Sstevel@tonic-gateretrieve this information, call uploadInfo(). It returns a reference to 5615*0Sstevel@tonic-gatean associative array containing all the document headers. 5616*0Sstevel@tonic-gate 5617*0Sstevel@tonic-gate $filename = $query->param('uploaded_file'); 5618*0Sstevel@tonic-gate $type = $query->uploadInfo($filename)->{'Content-Type'}; 5619*0Sstevel@tonic-gate unless ($type eq 'text/html') { 5620*0Sstevel@tonic-gate die "HTML FILES ONLY!"; 5621*0Sstevel@tonic-gate } 5622*0Sstevel@tonic-gate 5623*0Sstevel@tonic-gateIf you are using a machine that recognizes "text" and "binary" data 5624*0Sstevel@tonic-gatemodes, be sure to understand when and how to use them (see the Camel book). 5625*0Sstevel@tonic-gateOtherwise you may find that binary files are corrupted during file 5626*0Sstevel@tonic-gateuploads. 5627*0Sstevel@tonic-gate 5628*0Sstevel@tonic-gateThere are occasionally problems involving parsing the uploaded file. 5629*0Sstevel@tonic-gateThis usually happens when the user presses "Stop" before the upload is 5630*0Sstevel@tonic-gatefinished. In this case, CGI.pm will return undef for the name of the 5631*0Sstevel@tonic-gateuploaded file and set I<cgi_error()> to the string "400 Bad request 5632*0Sstevel@tonic-gate(malformed multipart POST)". This error message is designed so that 5633*0Sstevel@tonic-gateyou can incorporate it into a status code to be sent to the browser. 5634*0Sstevel@tonic-gateExample: 5635*0Sstevel@tonic-gate 5636*0Sstevel@tonic-gate $file = $query->upload('uploaded_file'); 5637*0Sstevel@tonic-gate if (!$file && $query->cgi_error) { 5638*0Sstevel@tonic-gate print $query->header(-status=>$query->cgi_error); 5639*0Sstevel@tonic-gate exit 0; 5640*0Sstevel@tonic-gate } 5641*0Sstevel@tonic-gate 5642*0Sstevel@tonic-gateYou are free to create a custom HTML page to complain about the error, 5643*0Sstevel@tonic-gateif you wish. 5644*0Sstevel@tonic-gate 5645*0Sstevel@tonic-gateYou can set up a callback that will be called whenever a file upload 5646*0Sstevel@tonic-gateis being read during the form processing. This is much like the 5647*0Sstevel@tonic-gateUPLOAD_HOOK facility available in Apache::Request, with the exception 5648*0Sstevel@tonic-gatethat the first argument to the callback is an Apache::Upload object, 5649*0Sstevel@tonic-gatehere it's the remote filename. 5650*0Sstevel@tonic-gate 5651*0Sstevel@tonic-gate $q = CGI->new(); 5652*0Sstevel@tonic-gate $q->upload_hook(\&hook,$data); 5653*0Sstevel@tonic-gate 5654*0Sstevel@tonic-gate sub hook 5655*0Sstevel@tonic-gate { 5656*0Sstevel@tonic-gate my ($filename, $buffer, $bytes_read, $data) = @_; 5657*0Sstevel@tonic-gate print "Read $bytes_read bytes of $filename\n"; 5658*0Sstevel@tonic-gate } 5659*0Sstevel@tonic-gate 5660*0Sstevel@tonic-gateIf using the function-oriented interface, call the CGI::upload_hook() 5661*0Sstevel@tonic-gatemethod before calling param() or any other CGI functions: 5662*0Sstevel@tonic-gate 5663*0Sstevel@tonic-gate CGI::upload_hook(\&hook,$data); 5664*0Sstevel@tonic-gate 5665*0Sstevel@tonic-gateThis method is not exported by default. You will have to import it 5666*0Sstevel@tonic-gateexplicitly if you wish to use it without the CGI:: prefix. 5667*0Sstevel@tonic-gate 5668*0Sstevel@tonic-gateIf you are using CGI.pm on a Windows platform and find that binary 5669*0Sstevel@tonic-gatefiles get slightly larger when uploaded but that text files remain the 5670*0Sstevel@tonic-gatesame, then you have forgotten to activate binary mode on the output 5671*0Sstevel@tonic-gatefilehandle. Be sure to call binmode() on any handle that you create 5672*0Sstevel@tonic-gateto write the uploaded file to disk. 5673*0Sstevel@tonic-gate 5674*0Sstevel@tonic-gateJAVASCRIPTING: The B<-onChange>, B<-onFocus>, B<-onBlur>, 5675*0Sstevel@tonic-gateB<-onMouseOver>, B<-onMouseOut> and B<-onSelect> parameters are 5676*0Sstevel@tonic-gaterecognized. See textfield() for details. 5677*0Sstevel@tonic-gate 5678*0Sstevel@tonic-gate=head2 CREATING A POPUP MENU 5679*0Sstevel@tonic-gate 5680*0Sstevel@tonic-gate print $query->popup_menu('menu_name', 5681*0Sstevel@tonic-gate ['eenie','meenie','minie'], 5682*0Sstevel@tonic-gate 'meenie'); 5683*0Sstevel@tonic-gate 5684*0Sstevel@tonic-gate -or- 5685*0Sstevel@tonic-gate 5686*0Sstevel@tonic-gate %labels = ('eenie'=>'your first choice', 5687*0Sstevel@tonic-gate 'meenie'=>'your second choice', 5688*0Sstevel@tonic-gate 'minie'=>'your third choice'); 5689*0Sstevel@tonic-gate %attributes = ('eenie'=>{'class'=>'class of first choice'}); 5690*0Sstevel@tonic-gate print $query->popup_menu('menu_name', 5691*0Sstevel@tonic-gate ['eenie','meenie','minie'], 5692*0Sstevel@tonic-gate 'meenie',\%labels,\%attributes); 5693*0Sstevel@tonic-gate 5694*0Sstevel@tonic-gate -or (named parameter style)- 5695*0Sstevel@tonic-gate 5696*0Sstevel@tonic-gate print $query->popup_menu(-name=>'menu_name', 5697*0Sstevel@tonic-gate -values=>['eenie','meenie','minie'], 5698*0Sstevel@tonic-gate -default=>'meenie', 5699*0Sstevel@tonic-gate -labels=>\%labels, 5700*0Sstevel@tonic-gate -attributes=>\%attributes); 5701*0Sstevel@tonic-gate 5702*0Sstevel@tonic-gatepopup_menu() creates a menu. 5703*0Sstevel@tonic-gate 5704*0Sstevel@tonic-gate=over 4 5705*0Sstevel@tonic-gate 5706*0Sstevel@tonic-gate=item 1. 5707*0Sstevel@tonic-gate 5708*0Sstevel@tonic-gateThe required first argument is the menu's name (-name). 5709*0Sstevel@tonic-gate 5710*0Sstevel@tonic-gate=item 2. 5711*0Sstevel@tonic-gate 5712*0Sstevel@tonic-gateThe required second argument (-values) is an array B<reference> 5713*0Sstevel@tonic-gatecontaining the list of menu items in the menu. You can pass the 5714*0Sstevel@tonic-gatemethod an anonymous array, as shown in the example, or a reference to 5715*0Sstevel@tonic-gatea named array, such as "\@foo". 5716*0Sstevel@tonic-gate 5717*0Sstevel@tonic-gate=item 3. 5718*0Sstevel@tonic-gate 5719*0Sstevel@tonic-gateThe optional third parameter (-default) is the name of the default 5720*0Sstevel@tonic-gatemenu choice. If not specified, the first item will be the default. 5721*0Sstevel@tonic-gateThe values of the previous choice will be maintained across queries. 5722*0Sstevel@tonic-gate 5723*0Sstevel@tonic-gate=item 4. 5724*0Sstevel@tonic-gate 5725*0Sstevel@tonic-gateThe optional fourth parameter (-labels) is provided for people who 5726*0Sstevel@tonic-gatewant to use different values for the user-visible label inside the 5727*0Sstevel@tonic-gatepopup menu and the value returned to your script. It's a pointer to an 5728*0Sstevel@tonic-gateassociative array relating menu values to user-visible labels. If you 5729*0Sstevel@tonic-gateleave this parameter blank, the menu values will be displayed by 5730*0Sstevel@tonic-gatedefault. (You can also leave a label undefined if you want to). 5731*0Sstevel@tonic-gate 5732*0Sstevel@tonic-gate=item 5. 5733*0Sstevel@tonic-gate 5734*0Sstevel@tonic-gateThe optional fifth parameter (-attributes) is provided to assign 5735*0Sstevel@tonic-gateany of the common HTML attributes to an individual menu item. It's 5736*0Sstevel@tonic-gatea pointer to an associative array relating menu values to another 5737*0Sstevel@tonic-gateassociative array with the attribute's name as the key and the 5738*0Sstevel@tonic-gateattribute's value as the value. 5739*0Sstevel@tonic-gate 5740*0Sstevel@tonic-gate=back 5741*0Sstevel@tonic-gate 5742*0Sstevel@tonic-gateWhen the form is processed, the selected value of the popup menu can 5743*0Sstevel@tonic-gatebe retrieved using: 5744*0Sstevel@tonic-gate 5745*0Sstevel@tonic-gate $popup_menu_value = $query->param('menu_name'); 5746*0Sstevel@tonic-gate 5747*0Sstevel@tonic-gateJAVASCRIPTING: popup_menu() recognizes the following event handlers: 5748*0Sstevel@tonic-gateB<-onChange>, B<-onFocus>, B<-onMouseOver>, B<-onMouseOut>, and 5749*0Sstevel@tonic-gateB<-onBlur>. See the textfield() section for details on when these 5750*0Sstevel@tonic-gatehandlers are called. 5751*0Sstevel@tonic-gate 5752*0Sstevel@tonic-gate=head2 CREATING AN OPTION GROUP 5753*0Sstevel@tonic-gate 5754*0Sstevel@tonic-gateNamed parameter style 5755*0Sstevel@tonic-gate 5756*0Sstevel@tonic-gate print $query->popup_menu(-name=>'menu_name', 5757*0Sstevel@tonic-gate -values=>[qw/eenie meenie minie/, 5758*0Sstevel@tonic-gate $q->optgroup(-name=>'optgroup_name', 5759*0Sstevel@tonic-gate -values ['moe','catch'], 5760*0Sstevel@tonic-gate -attributes=>{'catch'=>{'class'=>'red'}}), 5761*0Sstevel@tonic-gate -labels=>{'eenie'=>'one', 5762*0Sstevel@tonic-gate 'meenie'=>'two', 5763*0Sstevel@tonic-gate 'minie'=>'three'}, 5764*0Sstevel@tonic-gate -default=>'meenie'); 5765*0Sstevel@tonic-gate 5766*0Sstevel@tonic-gate Old style 5767*0Sstevel@tonic-gate print $query->popup_menu('menu_name', 5768*0Sstevel@tonic-gate ['eenie','meenie','minie', 5769*0Sstevel@tonic-gate $q->optgroup('optgroup_name', ['moe', 'catch'], 5770*0Sstevel@tonic-gate {'catch'=>{'class'=>'red'}})],'meenie', 5771*0Sstevel@tonic-gate {'eenie'=>'one','meenie'=>'two','minie'=>'three'}); 5772*0Sstevel@tonic-gate 5773*0Sstevel@tonic-gateoptgroup creates an option group within a popup menu. 5774*0Sstevel@tonic-gate 5775*0Sstevel@tonic-gate=over 4 5776*0Sstevel@tonic-gate 5777*0Sstevel@tonic-gate=item 1. 5778*0Sstevel@tonic-gate 5779*0Sstevel@tonic-gateThe required first argument (B<-name>) is the label attribute of the 5780*0Sstevel@tonic-gateoptgroup and is B<not> inserted in the parameter list of the query. 5781*0Sstevel@tonic-gate 5782*0Sstevel@tonic-gate=item 2. 5783*0Sstevel@tonic-gate 5784*0Sstevel@tonic-gateThe required second argument (B<-values>) is an array reference 5785*0Sstevel@tonic-gatecontaining the list of menu items in the menu. You can pass the 5786*0Sstevel@tonic-gatemethod an anonymous array, as shown in the example, or a reference 5787*0Sstevel@tonic-gateto a named array, such as \@foo. If you pass a HASH reference, 5788*0Sstevel@tonic-gatethe keys will be used for the menu values, and the values will be 5789*0Sstevel@tonic-gateused for the menu labels (see -labels below). 5790*0Sstevel@tonic-gate 5791*0Sstevel@tonic-gate=item 3. 5792*0Sstevel@tonic-gate 5793*0Sstevel@tonic-gateThe optional third parameter (B<-labels>) allows you to pass a reference 5794*0Sstevel@tonic-gateto an associative array containing user-visible labels for one or more 5795*0Sstevel@tonic-gateof the menu items. You can use this when you want the user to see one 5796*0Sstevel@tonic-gatemenu string, but have the browser return your program a different one. 5797*0Sstevel@tonic-gateIf you don't specify this, the value string will be used instead 5798*0Sstevel@tonic-gate("eenie", "meenie" and "minie" in this example). This is equivalent 5799*0Sstevel@tonic-gateto using a hash reference for the -values parameter. 5800*0Sstevel@tonic-gate 5801*0Sstevel@tonic-gate=item 4. 5802*0Sstevel@tonic-gate 5803*0Sstevel@tonic-gateAn optional fourth parameter (B<-labeled>) can be set to a true value 5804*0Sstevel@tonic-gateand indicates that the values should be used as the label attribute 5805*0Sstevel@tonic-gatefor each option element within the optgroup. 5806*0Sstevel@tonic-gate 5807*0Sstevel@tonic-gate=item 5. 5808*0Sstevel@tonic-gate 5809*0Sstevel@tonic-gateAn optional fifth parameter (-novals) can be set to a true value and 5810*0Sstevel@tonic-gateindicates to suppress the val attribut in each option element within 5811*0Sstevel@tonic-gatethe optgroup. 5812*0Sstevel@tonic-gate 5813*0Sstevel@tonic-gateSee the discussion on optgroup at W3C 5814*0Sstevel@tonic-gate(http://www.w3.org/TR/REC-html40/interact/forms.html#edef-OPTGROUP) 5815*0Sstevel@tonic-gatefor details. 5816*0Sstevel@tonic-gate 5817*0Sstevel@tonic-gate=item 6. 5818*0Sstevel@tonic-gate 5819*0Sstevel@tonic-gateAn optional sixth parameter (-attributes) is provided to assign 5820*0Sstevel@tonic-gateany of the common HTML attributes to an individual menu item. It's 5821*0Sstevel@tonic-gatea pointer to an associative array relating menu values to another 5822*0Sstevel@tonic-gateassociative array with the attribute's name as the key and the 5823*0Sstevel@tonic-gateattribute's value as the value. 5824*0Sstevel@tonic-gate 5825*0Sstevel@tonic-gate=back 5826*0Sstevel@tonic-gate 5827*0Sstevel@tonic-gate=head2 CREATING A SCROLLING LIST 5828*0Sstevel@tonic-gate 5829*0Sstevel@tonic-gate print $query->scrolling_list('list_name', 5830*0Sstevel@tonic-gate ['eenie','meenie','minie','moe'], 5831*0Sstevel@tonic-gate ['eenie','moe'],5,'true',{'moe'=>{'class'=>'red'}}); 5832*0Sstevel@tonic-gate -or- 5833*0Sstevel@tonic-gate 5834*0Sstevel@tonic-gate print $query->scrolling_list('list_name', 5835*0Sstevel@tonic-gate ['eenie','meenie','minie','moe'], 5836*0Sstevel@tonic-gate ['eenie','moe'],5,'true', 5837*0Sstevel@tonic-gate \%labels,%attributes); 5838*0Sstevel@tonic-gate 5839*0Sstevel@tonic-gate -or- 5840*0Sstevel@tonic-gate 5841*0Sstevel@tonic-gate print $query->scrolling_list(-name=>'list_name', 5842*0Sstevel@tonic-gate -values=>['eenie','meenie','minie','moe'], 5843*0Sstevel@tonic-gate -default=>['eenie','moe'], 5844*0Sstevel@tonic-gate -size=>5, 5845*0Sstevel@tonic-gate -multiple=>'true', 5846*0Sstevel@tonic-gate -labels=>\%labels, 5847*0Sstevel@tonic-gate -attributes=>\%attributes); 5848*0Sstevel@tonic-gate 5849*0Sstevel@tonic-gatescrolling_list() creates a scrolling list. 5850*0Sstevel@tonic-gate 5851*0Sstevel@tonic-gate=over 4 5852*0Sstevel@tonic-gate 5853*0Sstevel@tonic-gate=item B<Parameters:> 5854*0Sstevel@tonic-gate 5855*0Sstevel@tonic-gate=item 1. 5856*0Sstevel@tonic-gate 5857*0Sstevel@tonic-gateThe first and second arguments are the list name (-name) and values 5858*0Sstevel@tonic-gate(-values). As in the popup menu, the second argument should be an 5859*0Sstevel@tonic-gatearray reference. 5860*0Sstevel@tonic-gate 5861*0Sstevel@tonic-gate=item 2. 5862*0Sstevel@tonic-gate 5863*0Sstevel@tonic-gateThe optional third argument (-default) can be either a reference to a 5864*0Sstevel@tonic-gatelist containing the values to be selected by default, or can be a 5865*0Sstevel@tonic-gatesingle value to select. If this argument is missing or undefined, 5866*0Sstevel@tonic-gatethen nothing is selected when the list first appears. In the named 5867*0Sstevel@tonic-gateparameter version, you can use the synonym "-defaults" for this 5868*0Sstevel@tonic-gateparameter. 5869*0Sstevel@tonic-gate 5870*0Sstevel@tonic-gate=item 3. 5871*0Sstevel@tonic-gate 5872*0Sstevel@tonic-gateThe optional fourth argument is the size of the list (-size). 5873*0Sstevel@tonic-gate 5874*0Sstevel@tonic-gate=item 4. 5875*0Sstevel@tonic-gate 5876*0Sstevel@tonic-gateThe optional fifth argument can be set to true to allow multiple 5877*0Sstevel@tonic-gatesimultaneous selections (-multiple). Otherwise only one selection 5878*0Sstevel@tonic-gatewill be allowed at a time. 5879*0Sstevel@tonic-gate 5880*0Sstevel@tonic-gate=item 5. 5881*0Sstevel@tonic-gate 5882*0Sstevel@tonic-gateThe optional sixth argument is a pointer to an associative array 5883*0Sstevel@tonic-gatecontaining long user-visible labels for the list items (-labels). 5884*0Sstevel@tonic-gateIf not provided, the values will be displayed. 5885*0Sstevel@tonic-gate 5886*0Sstevel@tonic-gate=item 6. 5887*0Sstevel@tonic-gate 5888*0Sstevel@tonic-gateThe optional sixth parameter (-attributes) is provided to assign 5889*0Sstevel@tonic-gateany of the common HTML attributes to an individual menu item. It's 5890*0Sstevel@tonic-gatea pointer to an associative array relating menu values to another 5891*0Sstevel@tonic-gateassociative array with the attribute's name as the key and the 5892*0Sstevel@tonic-gateattribute's value as the value. 5893*0Sstevel@tonic-gate 5894*0Sstevel@tonic-gateWhen this form is processed, all selected list items will be returned as 5895*0Sstevel@tonic-gatea list under the parameter name 'list_name'. The values of the 5896*0Sstevel@tonic-gateselected items can be retrieved with: 5897*0Sstevel@tonic-gate 5898*0Sstevel@tonic-gate @selected = $query->param('list_name'); 5899*0Sstevel@tonic-gate 5900*0Sstevel@tonic-gate=back 5901*0Sstevel@tonic-gate 5902*0Sstevel@tonic-gateJAVASCRIPTING: scrolling_list() recognizes the following event 5903*0Sstevel@tonic-gatehandlers: B<-onChange>, B<-onFocus>, B<-onMouseOver>, B<-onMouseOut> 5904*0Sstevel@tonic-gateand B<-onBlur>. See textfield() for the description of when these 5905*0Sstevel@tonic-gatehandlers are called. 5906*0Sstevel@tonic-gate 5907*0Sstevel@tonic-gate=head2 CREATING A GROUP OF RELATED CHECKBOXES 5908*0Sstevel@tonic-gate 5909*0Sstevel@tonic-gate print $query->checkbox_group(-name=>'group_name', 5910*0Sstevel@tonic-gate -values=>['eenie','meenie','minie','moe'], 5911*0Sstevel@tonic-gate -default=>['eenie','moe'], 5912*0Sstevel@tonic-gate -linebreak=>'true', 5913*0Sstevel@tonic-gate -labels=>\%labels, 5914*0Sstevel@tonic-gate -attributes=>\%attributes); 5915*0Sstevel@tonic-gate 5916*0Sstevel@tonic-gate print $query->checkbox_group('group_name', 5917*0Sstevel@tonic-gate ['eenie','meenie','minie','moe'], 5918*0Sstevel@tonic-gate ['eenie','moe'],'true',\%labels, 5919*0Sstevel@tonic-gate {'moe'=>{'class'=>'red'}}); 5920*0Sstevel@tonic-gate 5921*0Sstevel@tonic-gate HTML3-COMPATIBLE BROWSERS ONLY: 5922*0Sstevel@tonic-gate 5923*0Sstevel@tonic-gate print $query->checkbox_group(-name=>'group_name', 5924*0Sstevel@tonic-gate -values=>['eenie','meenie','minie','moe'], 5925*0Sstevel@tonic-gate -rows=2,-columns=>2); 5926*0Sstevel@tonic-gate 5927*0Sstevel@tonic-gate 5928*0Sstevel@tonic-gatecheckbox_group() creates a list of checkboxes that are related 5929*0Sstevel@tonic-gateby the same name. 5930*0Sstevel@tonic-gate 5931*0Sstevel@tonic-gate=over 4 5932*0Sstevel@tonic-gate 5933*0Sstevel@tonic-gate=item B<Parameters:> 5934*0Sstevel@tonic-gate 5935*0Sstevel@tonic-gate=item 1. 5936*0Sstevel@tonic-gate 5937*0Sstevel@tonic-gateThe first and second arguments are the checkbox name and values, 5938*0Sstevel@tonic-gaterespectively (-name and -values). As in the popup menu, the second 5939*0Sstevel@tonic-gateargument should be an array reference. These values are used for the 5940*0Sstevel@tonic-gateuser-readable labels printed next to the checkboxes as well as for the 5941*0Sstevel@tonic-gatevalues passed to your script in the query string. 5942*0Sstevel@tonic-gate 5943*0Sstevel@tonic-gate=item 2. 5944*0Sstevel@tonic-gate 5945*0Sstevel@tonic-gateThe optional third argument (-default) can be either a reference to a 5946*0Sstevel@tonic-gatelist containing the values to be checked by default, or can be a 5947*0Sstevel@tonic-gatesingle value to checked. If this argument is missing or undefined, 5948*0Sstevel@tonic-gatethen nothing is selected when the list first appears. 5949*0Sstevel@tonic-gate 5950*0Sstevel@tonic-gate=item 3. 5951*0Sstevel@tonic-gate 5952*0Sstevel@tonic-gateThe optional fourth argument (-linebreak) can be set to true to place 5953*0Sstevel@tonic-gateline breaks between the checkboxes so that they appear as a vertical 5954*0Sstevel@tonic-gatelist. Otherwise, they will be strung together on a horizontal line. 5955*0Sstevel@tonic-gate 5956*0Sstevel@tonic-gate=item 4. 5957*0Sstevel@tonic-gate 5958*0Sstevel@tonic-gateThe optional fifth argument is a pointer to an associative array 5959*0Sstevel@tonic-gaterelating the checkbox values to the user-visible labels that will 5960*0Sstevel@tonic-gatebe printed next to them (-labels). If not provided, the values will 5961*0Sstevel@tonic-gatebe used as the default. 5962*0Sstevel@tonic-gate 5963*0Sstevel@tonic-gate=item 5. 5964*0Sstevel@tonic-gate 5965*0Sstevel@tonic-gateB<HTML3-compatible browsers> (such as Netscape) can take advantage of 5966*0Sstevel@tonic-gatethe optional parameters B<-rows>, and B<-columns>. These parameters 5967*0Sstevel@tonic-gatecause checkbox_group() to return an HTML3 compatible table containing 5968*0Sstevel@tonic-gatethe checkbox group formatted with the specified number of rows and 5969*0Sstevel@tonic-gatecolumns. You can provide just the -columns parameter if you wish; 5970*0Sstevel@tonic-gatecheckbox_group will calculate the correct number of rows for you. 5971*0Sstevel@tonic-gate 5972*0Sstevel@tonic-gate=item 6. 5973*0Sstevel@tonic-gate 5974*0Sstevel@tonic-gateThe optional sixth parameter (-attributes) is provided to assign 5975*0Sstevel@tonic-gateany of the common HTML attributes to an individual menu item. It's 5976*0Sstevel@tonic-gatea pointer to an associative array relating menu values to another 5977*0Sstevel@tonic-gateassociative array with the attribute's name as the key and the 5978*0Sstevel@tonic-gateattribute's value as the value. 5979*0Sstevel@tonic-gate 5980*0Sstevel@tonic-gateTo include row and column headings in the returned table, you 5981*0Sstevel@tonic-gatecan use the B<-rowheaders> and B<-colheaders> parameters. Both 5982*0Sstevel@tonic-gateof these accept a pointer to an array of headings to use. 5983*0Sstevel@tonic-gateThe headings are just decorative. They don't reorganize the 5984*0Sstevel@tonic-gateinterpretation of the checkboxes -- they're still a single named 5985*0Sstevel@tonic-gateunit. 5986*0Sstevel@tonic-gate 5987*0Sstevel@tonic-gate=back 5988*0Sstevel@tonic-gate 5989*0Sstevel@tonic-gateWhen the form is processed, all checked boxes will be returned as 5990*0Sstevel@tonic-gatea list under the parameter name 'group_name'. The values of the 5991*0Sstevel@tonic-gate"on" checkboxes can be retrieved with: 5992*0Sstevel@tonic-gate 5993*0Sstevel@tonic-gate @turned_on = $query->param('group_name'); 5994*0Sstevel@tonic-gate 5995*0Sstevel@tonic-gateThe value returned by checkbox_group() is actually an array of button 5996*0Sstevel@tonic-gateelements. You can capture them and use them within tables, lists, 5997*0Sstevel@tonic-gateor in other creative ways: 5998*0Sstevel@tonic-gate 5999*0Sstevel@tonic-gate @h = $query->checkbox_group(-name=>'group_name',-values=>\@values); 6000*0Sstevel@tonic-gate &use_in_creative_way(@h); 6001*0Sstevel@tonic-gate 6002*0Sstevel@tonic-gateJAVASCRIPTING: checkbox_group() recognizes the B<-onClick> 6003*0Sstevel@tonic-gateparameter. This specifies a JavaScript code fragment or 6004*0Sstevel@tonic-gatefunction call to be executed every time the user clicks on 6005*0Sstevel@tonic-gateany of the buttons in the group. You can retrieve the identity 6006*0Sstevel@tonic-gateof the particular button clicked on using the "this" variable. 6007*0Sstevel@tonic-gate 6008*0Sstevel@tonic-gate=head2 CREATING A STANDALONE CHECKBOX 6009*0Sstevel@tonic-gate 6010*0Sstevel@tonic-gate print $query->checkbox(-name=>'checkbox_name', 6011*0Sstevel@tonic-gate -checked=>1, 6012*0Sstevel@tonic-gate -value=>'ON', 6013*0Sstevel@tonic-gate -label=>'CLICK ME'); 6014*0Sstevel@tonic-gate 6015*0Sstevel@tonic-gate -or- 6016*0Sstevel@tonic-gate 6017*0Sstevel@tonic-gate print $query->checkbox('checkbox_name','checked','ON','CLICK ME'); 6018*0Sstevel@tonic-gate 6019*0Sstevel@tonic-gatecheckbox() is used to create an isolated checkbox that isn't logically 6020*0Sstevel@tonic-gaterelated to any others. 6021*0Sstevel@tonic-gate 6022*0Sstevel@tonic-gate=over 4 6023*0Sstevel@tonic-gate 6024*0Sstevel@tonic-gate=item B<Parameters:> 6025*0Sstevel@tonic-gate 6026*0Sstevel@tonic-gate=item 1. 6027*0Sstevel@tonic-gate 6028*0Sstevel@tonic-gateThe first parameter is the required name for the checkbox (-name). It 6029*0Sstevel@tonic-gatewill also be used for the user-readable label printed next to the 6030*0Sstevel@tonic-gatecheckbox. 6031*0Sstevel@tonic-gate 6032*0Sstevel@tonic-gate=item 2. 6033*0Sstevel@tonic-gate 6034*0Sstevel@tonic-gateThe optional second parameter (-checked) specifies that the checkbox 6035*0Sstevel@tonic-gateis turned on by default. Synonyms are -selected and -on. 6036*0Sstevel@tonic-gate 6037*0Sstevel@tonic-gate=item 3. 6038*0Sstevel@tonic-gate 6039*0Sstevel@tonic-gateThe optional third parameter (-value) specifies the value of the 6040*0Sstevel@tonic-gatecheckbox when it is checked. If not provided, the word "on" is 6041*0Sstevel@tonic-gateassumed. 6042*0Sstevel@tonic-gate 6043*0Sstevel@tonic-gate=item 4. 6044*0Sstevel@tonic-gate 6045*0Sstevel@tonic-gateThe optional fourth parameter (-label) is the user-readable label to 6046*0Sstevel@tonic-gatebe attached to the checkbox. If not provided, the checkbox name is 6047*0Sstevel@tonic-gateused. 6048*0Sstevel@tonic-gate 6049*0Sstevel@tonic-gate=back 6050*0Sstevel@tonic-gate 6051*0Sstevel@tonic-gateThe value of the checkbox can be retrieved using: 6052*0Sstevel@tonic-gate 6053*0Sstevel@tonic-gate $turned_on = $query->param('checkbox_name'); 6054*0Sstevel@tonic-gate 6055*0Sstevel@tonic-gateJAVASCRIPTING: checkbox() recognizes the B<-onClick> 6056*0Sstevel@tonic-gateparameter. See checkbox_group() for further details. 6057*0Sstevel@tonic-gate 6058*0Sstevel@tonic-gate=head2 CREATING A RADIO BUTTON GROUP 6059*0Sstevel@tonic-gate 6060*0Sstevel@tonic-gate print $query->radio_group(-name=>'group_name', 6061*0Sstevel@tonic-gate -values=>['eenie','meenie','minie'], 6062*0Sstevel@tonic-gate -default=>'meenie', 6063*0Sstevel@tonic-gate -linebreak=>'true', 6064*0Sstevel@tonic-gate -labels=>\%labels, 6065*0Sstevel@tonic-gate -attributes=>\%attributes); 6066*0Sstevel@tonic-gate 6067*0Sstevel@tonic-gate -or- 6068*0Sstevel@tonic-gate 6069*0Sstevel@tonic-gate print $query->radio_group('group_name',['eenie','meenie','minie'], 6070*0Sstevel@tonic-gate 'meenie','true',\%labels,\%attributes); 6071*0Sstevel@tonic-gate 6072*0Sstevel@tonic-gate 6073*0Sstevel@tonic-gate HTML3-COMPATIBLE BROWSERS ONLY: 6074*0Sstevel@tonic-gate 6075*0Sstevel@tonic-gate print $query->radio_group(-name=>'group_name', 6076*0Sstevel@tonic-gate -values=>['eenie','meenie','minie','moe'], 6077*0Sstevel@tonic-gate -rows=2,-columns=>2); 6078*0Sstevel@tonic-gate 6079*0Sstevel@tonic-gateradio_group() creates a set of logically-related radio buttons 6080*0Sstevel@tonic-gate(turning one member of the group on turns the others off) 6081*0Sstevel@tonic-gate 6082*0Sstevel@tonic-gate=over 4 6083*0Sstevel@tonic-gate 6084*0Sstevel@tonic-gate=item B<Parameters:> 6085*0Sstevel@tonic-gate 6086*0Sstevel@tonic-gate=item 1. 6087*0Sstevel@tonic-gate 6088*0Sstevel@tonic-gateThe first argument is the name of the group and is required (-name). 6089*0Sstevel@tonic-gate 6090*0Sstevel@tonic-gate=item 2. 6091*0Sstevel@tonic-gate 6092*0Sstevel@tonic-gateThe second argument (-values) is the list of values for the radio 6093*0Sstevel@tonic-gatebuttons. The values and the labels that appear on the page are 6094*0Sstevel@tonic-gateidentical. Pass an array I<reference> in the second argument, either 6095*0Sstevel@tonic-gateusing an anonymous array, as shown, or by referencing a named array as 6096*0Sstevel@tonic-gatein "\@foo". 6097*0Sstevel@tonic-gate 6098*0Sstevel@tonic-gate=item 3. 6099*0Sstevel@tonic-gate 6100*0Sstevel@tonic-gateThe optional third parameter (-default) is the name of the default 6101*0Sstevel@tonic-gatebutton to turn on. If not specified, the first item will be the 6102*0Sstevel@tonic-gatedefault. You can provide a nonexistent button name, such as "-" to 6103*0Sstevel@tonic-gatestart up with no buttons selected. 6104*0Sstevel@tonic-gate 6105*0Sstevel@tonic-gate=item 4. 6106*0Sstevel@tonic-gate 6107*0Sstevel@tonic-gateThe optional fourth parameter (-linebreak) can be set to 'true' to put 6108*0Sstevel@tonic-gateline breaks between the buttons, creating a vertical list. 6109*0Sstevel@tonic-gate 6110*0Sstevel@tonic-gate=item 5. 6111*0Sstevel@tonic-gate 6112*0Sstevel@tonic-gateThe optional fifth parameter (-labels) is a pointer to an associative 6113*0Sstevel@tonic-gatearray relating the radio button values to user-visible labels to be 6114*0Sstevel@tonic-gateused in the display. If not provided, the values themselves are 6115*0Sstevel@tonic-gatedisplayed. 6116*0Sstevel@tonic-gate 6117*0Sstevel@tonic-gate=item 6. 6118*0Sstevel@tonic-gate 6119*0Sstevel@tonic-gateB<HTML3-compatible browsers> (such as Netscape) can take advantage 6120*0Sstevel@tonic-gateof the optional 6121*0Sstevel@tonic-gateparameters B<-rows>, and B<-columns>. These parameters cause 6122*0Sstevel@tonic-gateradio_group() to return an HTML3 compatible table containing 6123*0Sstevel@tonic-gatethe radio group formatted with the specified number of rows 6124*0Sstevel@tonic-gateand columns. You can provide just the -columns parameter if you 6125*0Sstevel@tonic-gatewish; radio_group will calculate the correct number of rows 6126*0Sstevel@tonic-gatefor you. 6127*0Sstevel@tonic-gate 6128*0Sstevel@tonic-gate=item 6. 6129*0Sstevel@tonic-gate 6130*0Sstevel@tonic-gateThe optional sixth parameter (-attributes) is provided to assign 6131*0Sstevel@tonic-gateany of the common HTML attributes to an individual menu item. It's 6132*0Sstevel@tonic-gatea pointer to an associative array relating menu values to another 6133*0Sstevel@tonic-gateassociative array with the attribute's name as the key and the 6134*0Sstevel@tonic-gateattribute's value as the value. 6135*0Sstevel@tonic-gate 6136*0Sstevel@tonic-gateTo include row and column headings in the returned table, you 6137*0Sstevel@tonic-gatecan use the B<-rowheader> and B<-colheader> parameters. Both 6138*0Sstevel@tonic-gateof these accept a pointer to an array of headings to use. 6139*0Sstevel@tonic-gateThe headings are just decorative. They don't reorganize the 6140*0Sstevel@tonic-gateinterpretation of the radio buttons -- they're still a single named 6141*0Sstevel@tonic-gateunit. 6142*0Sstevel@tonic-gate 6143*0Sstevel@tonic-gate=back 6144*0Sstevel@tonic-gate 6145*0Sstevel@tonic-gateWhen the form is processed, the selected radio button can 6146*0Sstevel@tonic-gatebe retrieved using: 6147*0Sstevel@tonic-gate 6148*0Sstevel@tonic-gate $which_radio_button = $query->param('group_name'); 6149*0Sstevel@tonic-gate 6150*0Sstevel@tonic-gateThe value returned by radio_group() is actually an array of button 6151*0Sstevel@tonic-gateelements. You can capture them and use them within tables, lists, 6152*0Sstevel@tonic-gateor in other creative ways: 6153*0Sstevel@tonic-gate 6154*0Sstevel@tonic-gate @h = $query->radio_group(-name=>'group_name',-values=>\@values); 6155*0Sstevel@tonic-gate &use_in_creative_way(@h); 6156*0Sstevel@tonic-gate 6157*0Sstevel@tonic-gate=head2 CREATING A SUBMIT BUTTON 6158*0Sstevel@tonic-gate 6159*0Sstevel@tonic-gate print $query->submit(-name=>'button_name', 6160*0Sstevel@tonic-gate -value=>'value'); 6161*0Sstevel@tonic-gate 6162*0Sstevel@tonic-gate -or- 6163*0Sstevel@tonic-gate 6164*0Sstevel@tonic-gate print $query->submit('button_name','value'); 6165*0Sstevel@tonic-gate 6166*0Sstevel@tonic-gatesubmit() will create the query submission button. Every form 6167*0Sstevel@tonic-gateshould have one of these. 6168*0Sstevel@tonic-gate 6169*0Sstevel@tonic-gate=over 4 6170*0Sstevel@tonic-gate 6171*0Sstevel@tonic-gate=item B<Parameters:> 6172*0Sstevel@tonic-gate 6173*0Sstevel@tonic-gate=item 1. 6174*0Sstevel@tonic-gate 6175*0Sstevel@tonic-gateThe first argument (-name) is optional. You can give the button a 6176*0Sstevel@tonic-gatename if you have several submission buttons in your form and you want 6177*0Sstevel@tonic-gateto distinguish between them. The name will also be used as the 6178*0Sstevel@tonic-gateuser-visible label. Be aware that a few older browsers don't deal with this correctly and 6179*0Sstevel@tonic-gateB<never> send back a value from a button. 6180*0Sstevel@tonic-gate 6181*0Sstevel@tonic-gate=item 2. 6182*0Sstevel@tonic-gate 6183*0Sstevel@tonic-gateThe second argument (-value) is also optional. This gives the button 6184*0Sstevel@tonic-gatea value that will be passed to your script in the query string. 6185*0Sstevel@tonic-gate 6186*0Sstevel@tonic-gate=back 6187*0Sstevel@tonic-gate 6188*0Sstevel@tonic-gateYou can figure out which button was pressed by using different 6189*0Sstevel@tonic-gatevalues for each one: 6190*0Sstevel@tonic-gate 6191*0Sstevel@tonic-gate $which_one = $query->param('button_name'); 6192*0Sstevel@tonic-gate 6193*0Sstevel@tonic-gateJAVASCRIPTING: radio_group() recognizes the B<-onClick> 6194*0Sstevel@tonic-gateparameter. See checkbox_group() for further details. 6195*0Sstevel@tonic-gate 6196*0Sstevel@tonic-gate=head2 CREATING A RESET BUTTON 6197*0Sstevel@tonic-gate 6198*0Sstevel@tonic-gate print $query->reset 6199*0Sstevel@tonic-gate 6200*0Sstevel@tonic-gatereset() creates the "reset" button. Note that it restores the 6201*0Sstevel@tonic-gateform to its value from the last time the script was called, 6202*0Sstevel@tonic-gateNOT necessarily to the defaults. 6203*0Sstevel@tonic-gate 6204*0Sstevel@tonic-gateNote that this conflicts with the Perl reset() built-in. Use 6205*0Sstevel@tonic-gateCORE::reset() to get the original reset function. 6206*0Sstevel@tonic-gate 6207*0Sstevel@tonic-gate=head2 CREATING A DEFAULT BUTTON 6208*0Sstevel@tonic-gate 6209*0Sstevel@tonic-gate print $query->defaults('button_label') 6210*0Sstevel@tonic-gate 6211*0Sstevel@tonic-gatedefaults() creates a button that, when invoked, will cause the 6212*0Sstevel@tonic-gateform to be completely reset to its defaults, wiping out all the 6213*0Sstevel@tonic-gatechanges the user ever made. 6214*0Sstevel@tonic-gate 6215*0Sstevel@tonic-gate=head2 CREATING A HIDDEN FIELD 6216*0Sstevel@tonic-gate 6217*0Sstevel@tonic-gate print $query->hidden(-name=>'hidden_name', 6218*0Sstevel@tonic-gate -default=>['value1','value2'...]); 6219*0Sstevel@tonic-gate 6220*0Sstevel@tonic-gate -or- 6221*0Sstevel@tonic-gate 6222*0Sstevel@tonic-gate print $query->hidden('hidden_name','value1','value2'...); 6223*0Sstevel@tonic-gate 6224*0Sstevel@tonic-gatehidden() produces a text field that can't be seen by the user. It 6225*0Sstevel@tonic-gateis useful for passing state variable information from one invocation 6226*0Sstevel@tonic-gateof the script to the next. 6227*0Sstevel@tonic-gate 6228*0Sstevel@tonic-gate=over 4 6229*0Sstevel@tonic-gate 6230*0Sstevel@tonic-gate=item B<Parameters:> 6231*0Sstevel@tonic-gate 6232*0Sstevel@tonic-gate=item 1. 6233*0Sstevel@tonic-gate 6234*0Sstevel@tonic-gateThe first argument is required and specifies the name of this 6235*0Sstevel@tonic-gatefield (-name). 6236*0Sstevel@tonic-gate 6237*0Sstevel@tonic-gate=item 2. 6238*0Sstevel@tonic-gate 6239*0Sstevel@tonic-gateThe second argument is also required and specifies its value 6240*0Sstevel@tonic-gate(-default). In the named parameter style of calling, you can provide 6241*0Sstevel@tonic-gatea single value here or a reference to a whole list 6242*0Sstevel@tonic-gate 6243*0Sstevel@tonic-gate=back 6244*0Sstevel@tonic-gate 6245*0Sstevel@tonic-gateFetch the value of a hidden field this way: 6246*0Sstevel@tonic-gate 6247*0Sstevel@tonic-gate $hidden_value = $query->param('hidden_name'); 6248*0Sstevel@tonic-gate 6249*0Sstevel@tonic-gateNote, that just like all the other form elements, the value of a 6250*0Sstevel@tonic-gatehidden field is "sticky". If you want to replace a hidden field with 6251*0Sstevel@tonic-gatesome other values after the script has been called once you'll have to 6252*0Sstevel@tonic-gatedo it manually: 6253*0Sstevel@tonic-gate 6254*0Sstevel@tonic-gate $query->param('hidden_name','new','values','here'); 6255*0Sstevel@tonic-gate 6256*0Sstevel@tonic-gate=head2 CREATING A CLICKABLE IMAGE BUTTON 6257*0Sstevel@tonic-gate 6258*0Sstevel@tonic-gate print $query->image_button(-name=>'button_name', 6259*0Sstevel@tonic-gate -src=>'/source/URL', 6260*0Sstevel@tonic-gate -align=>'MIDDLE'); 6261*0Sstevel@tonic-gate 6262*0Sstevel@tonic-gate -or- 6263*0Sstevel@tonic-gate 6264*0Sstevel@tonic-gate print $query->image_button('button_name','/source/URL','MIDDLE'); 6265*0Sstevel@tonic-gate 6266*0Sstevel@tonic-gateimage_button() produces a clickable image. When it's clicked on the 6267*0Sstevel@tonic-gateposition of the click is returned to your script as "button_name.x" 6268*0Sstevel@tonic-gateand "button_name.y", where "button_name" is the name you've assigned 6269*0Sstevel@tonic-gateto it. 6270*0Sstevel@tonic-gate 6271*0Sstevel@tonic-gateJAVASCRIPTING: image_button() recognizes the B<-onClick> 6272*0Sstevel@tonic-gateparameter. See checkbox_group() for further details. 6273*0Sstevel@tonic-gate 6274*0Sstevel@tonic-gate=over 4 6275*0Sstevel@tonic-gate 6276*0Sstevel@tonic-gate=item B<Parameters:> 6277*0Sstevel@tonic-gate 6278*0Sstevel@tonic-gate=item 1. 6279*0Sstevel@tonic-gate 6280*0Sstevel@tonic-gateThe first argument (-name) is required and specifies the name of this 6281*0Sstevel@tonic-gatefield. 6282*0Sstevel@tonic-gate 6283*0Sstevel@tonic-gate=item 2. 6284*0Sstevel@tonic-gate 6285*0Sstevel@tonic-gateThe second argument (-src) is also required and specifies the URL 6286*0Sstevel@tonic-gate 6287*0Sstevel@tonic-gate=item 3. 6288*0Sstevel@tonic-gateThe third option (-align, optional) is an alignment type, and may be 6289*0Sstevel@tonic-gateTOP, BOTTOM or MIDDLE 6290*0Sstevel@tonic-gate 6291*0Sstevel@tonic-gate=back 6292*0Sstevel@tonic-gate 6293*0Sstevel@tonic-gateFetch the value of the button this way: 6294*0Sstevel@tonic-gate $x = $query->param('button_name.x'); 6295*0Sstevel@tonic-gate $y = $query->param('button_name.y'); 6296*0Sstevel@tonic-gate 6297*0Sstevel@tonic-gate=head2 CREATING A JAVASCRIPT ACTION BUTTON 6298*0Sstevel@tonic-gate 6299*0Sstevel@tonic-gate print $query->button(-name=>'button_name', 6300*0Sstevel@tonic-gate -value=>'user visible label', 6301*0Sstevel@tonic-gate -onClick=>"do_something()"); 6302*0Sstevel@tonic-gate 6303*0Sstevel@tonic-gate -or- 6304*0Sstevel@tonic-gate 6305*0Sstevel@tonic-gate print $query->button('button_name',"do_something()"); 6306*0Sstevel@tonic-gate 6307*0Sstevel@tonic-gatebutton() produces a button that is compatible with Netscape 2.0's 6308*0Sstevel@tonic-gateJavaScript. When it's pressed the fragment of JavaScript code 6309*0Sstevel@tonic-gatepointed to by the B<-onClick> parameter will be executed. On 6310*0Sstevel@tonic-gatenon-Netscape browsers this form element will probably not even 6311*0Sstevel@tonic-gatedisplay. 6312*0Sstevel@tonic-gate 6313*0Sstevel@tonic-gate=head1 HTTP COOKIES 6314*0Sstevel@tonic-gate 6315*0Sstevel@tonic-gateNetscape browsers versions 1.1 and higher, and all versions of 6316*0Sstevel@tonic-gateInternet Explorer, support a so-called "cookie" designed to help 6317*0Sstevel@tonic-gatemaintain state within a browser session. CGI.pm has several methods 6318*0Sstevel@tonic-gatethat support cookies. 6319*0Sstevel@tonic-gate 6320*0Sstevel@tonic-gateA cookie is a name=value pair much like the named parameters in a CGI 6321*0Sstevel@tonic-gatequery string. CGI scripts create one or more cookies and send 6322*0Sstevel@tonic-gatethem to the browser in the HTTP header. The browser maintains a list 6323*0Sstevel@tonic-gateof cookies that belong to a particular Web server, and returns them 6324*0Sstevel@tonic-gateto the CGI script during subsequent interactions. 6325*0Sstevel@tonic-gate 6326*0Sstevel@tonic-gateIn addition to the required name=value pair, each cookie has several 6327*0Sstevel@tonic-gateoptional attributes: 6328*0Sstevel@tonic-gate 6329*0Sstevel@tonic-gate=over 4 6330*0Sstevel@tonic-gate 6331*0Sstevel@tonic-gate=item 1. an expiration time 6332*0Sstevel@tonic-gate 6333*0Sstevel@tonic-gateThis is a time/date string (in a special GMT format) that indicates 6334*0Sstevel@tonic-gatewhen a cookie expires. The cookie will be saved and returned to your 6335*0Sstevel@tonic-gatescript until this expiration date is reached if the user exits 6336*0Sstevel@tonic-gatethe browser and restarts it. If an expiration date isn't specified, the cookie 6337*0Sstevel@tonic-gatewill remain active until the user quits the browser. 6338*0Sstevel@tonic-gate 6339*0Sstevel@tonic-gate=item 2. a domain 6340*0Sstevel@tonic-gate 6341*0Sstevel@tonic-gateThis is a partial or complete domain name for which the cookie is 6342*0Sstevel@tonic-gatevalid. The browser will return the cookie to any host that matches 6343*0Sstevel@tonic-gatethe partial domain name. For example, if you specify a domain name 6344*0Sstevel@tonic-gateof ".capricorn.com", then the browser will return the cookie to 6345*0Sstevel@tonic-gateWeb servers running on any of the machines "www.capricorn.com", 6346*0Sstevel@tonic-gate"www2.capricorn.com", "feckless.capricorn.com", etc. Domain names 6347*0Sstevel@tonic-gatemust contain at least two periods to prevent attempts to match 6348*0Sstevel@tonic-gateon top level domains like ".edu". If no domain is specified, then 6349*0Sstevel@tonic-gatethe browser will only return the cookie to servers on the host the 6350*0Sstevel@tonic-gatecookie originated from. 6351*0Sstevel@tonic-gate 6352*0Sstevel@tonic-gate=item 3. a path 6353*0Sstevel@tonic-gate 6354*0Sstevel@tonic-gateIf you provide a cookie path attribute, the browser will check it 6355*0Sstevel@tonic-gateagainst your script's URL before returning the cookie. For example, 6356*0Sstevel@tonic-gateif you specify the path "/cgi-bin", then the cookie will be returned 6357*0Sstevel@tonic-gateto each of the scripts "/cgi-bin/tally.pl", "/cgi-bin/order.pl", 6358*0Sstevel@tonic-gateand "/cgi-bin/customer_service/complain.pl", but not to the script 6359*0Sstevel@tonic-gate"/cgi-private/site_admin.pl". By default, path is set to "/", which 6360*0Sstevel@tonic-gatecauses the cookie to be sent to any CGI script on your site. 6361*0Sstevel@tonic-gate 6362*0Sstevel@tonic-gate=item 4. a "secure" flag 6363*0Sstevel@tonic-gate 6364*0Sstevel@tonic-gateIf the "secure" attribute is set, the cookie will only be sent to your 6365*0Sstevel@tonic-gatescript if the CGI request is occurring on a secure channel, such as SSL. 6366*0Sstevel@tonic-gate 6367*0Sstevel@tonic-gate=back 6368*0Sstevel@tonic-gate 6369*0Sstevel@tonic-gateThe interface to HTTP cookies is the B<cookie()> method: 6370*0Sstevel@tonic-gate 6371*0Sstevel@tonic-gate $cookie = $query->cookie(-name=>'sessionID', 6372*0Sstevel@tonic-gate -value=>'xyzzy', 6373*0Sstevel@tonic-gate -expires=>'+1h', 6374*0Sstevel@tonic-gate -path=>'/cgi-bin/database', 6375*0Sstevel@tonic-gate -domain=>'.capricorn.org', 6376*0Sstevel@tonic-gate -secure=>1); 6377*0Sstevel@tonic-gate print $query->header(-cookie=>$cookie); 6378*0Sstevel@tonic-gate 6379*0Sstevel@tonic-gateB<cookie()> creates a new cookie. Its parameters include: 6380*0Sstevel@tonic-gate 6381*0Sstevel@tonic-gate=over 4 6382*0Sstevel@tonic-gate 6383*0Sstevel@tonic-gate=item B<-name> 6384*0Sstevel@tonic-gate 6385*0Sstevel@tonic-gateThe name of the cookie (required). This can be any string at all. 6386*0Sstevel@tonic-gateAlthough browsers limit their cookie names to non-whitespace 6387*0Sstevel@tonic-gatealphanumeric characters, CGI.pm removes this restriction by escaping 6388*0Sstevel@tonic-gateand unescaping cookies behind the scenes. 6389*0Sstevel@tonic-gate 6390*0Sstevel@tonic-gate=item B<-value> 6391*0Sstevel@tonic-gate 6392*0Sstevel@tonic-gateThe value of the cookie. This can be any scalar value, 6393*0Sstevel@tonic-gatearray reference, or even associative array reference. For example, 6394*0Sstevel@tonic-gateyou can store an entire associative array into a cookie this way: 6395*0Sstevel@tonic-gate 6396*0Sstevel@tonic-gate $cookie=$query->cookie(-name=>'family information', 6397*0Sstevel@tonic-gate -value=>\%childrens_ages); 6398*0Sstevel@tonic-gate 6399*0Sstevel@tonic-gate=item B<-path> 6400*0Sstevel@tonic-gate 6401*0Sstevel@tonic-gateThe optional partial path for which this cookie will be valid, as described 6402*0Sstevel@tonic-gateabove. 6403*0Sstevel@tonic-gate 6404*0Sstevel@tonic-gate=item B<-domain> 6405*0Sstevel@tonic-gate 6406*0Sstevel@tonic-gateThe optional partial domain for which this cookie will be valid, as described 6407*0Sstevel@tonic-gateabove. 6408*0Sstevel@tonic-gate 6409*0Sstevel@tonic-gate=item B<-expires> 6410*0Sstevel@tonic-gate 6411*0Sstevel@tonic-gateThe optional expiration date for this cookie. The format is as described 6412*0Sstevel@tonic-gatein the section on the B<header()> method: 6413*0Sstevel@tonic-gate 6414*0Sstevel@tonic-gate "+1h" one hour from now 6415*0Sstevel@tonic-gate 6416*0Sstevel@tonic-gate=item B<-secure> 6417*0Sstevel@tonic-gate 6418*0Sstevel@tonic-gateIf set to true, this cookie will only be used within a secure 6419*0Sstevel@tonic-gateSSL session. 6420*0Sstevel@tonic-gate 6421*0Sstevel@tonic-gate=back 6422*0Sstevel@tonic-gate 6423*0Sstevel@tonic-gateThe cookie created by cookie() must be incorporated into the HTTP 6424*0Sstevel@tonic-gateheader within the string returned by the header() method: 6425*0Sstevel@tonic-gate 6426*0Sstevel@tonic-gate print $query->header(-cookie=>$my_cookie); 6427*0Sstevel@tonic-gate 6428*0Sstevel@tonic-gateTo create multiple cookies, give header() an array reference: 6429*0Sstevel@tonic-gate 6430*0Sstevel@tonic-gate $cookie1 = $query->cookie(-name=>'riddle_name', 6431*0Sstevel@tonic-gate -value=>"The Sphynx's Question"); 6432*0Sstevel@tonic-gate $cookie2 = $query->cookie(-name=>'answers', 6433*0Sstevel@tonic-gate -value=>\%answers); 6434*0Sstevel@tonic-gate print $query->header(-cookie=>[$cookie1,$cookie2]); 6435*0Sstevel@tonic-gate 6436*0Sstevel@tonic-gateTo retrieve a cookie, request it by name by calling cookie() method 6437*0Sstevel@tonic-gatewithout the B<-value> parameter: 6438*0Sstevel@tonic-gate 6439*0Sstevel@tonic-gate use CGI; 6440*0Sstevel@tonic-gate $query = new CGI; 6441*0Sstevel@tonic-gate $riddle = $query->cookie('riddle_name'); 6442*0Sstevel@tonic-gate %answers = $query->cookie('answers'); 6443*0Sstevel@tonic-gate 6444*0Sstevel@tonic-gateCookies created with a single scalar value, such as the "riddle_name" 6445*0Sstevel@tonic-gatecookie, will be returned in that form. Cookies with array and hash 6446*0Sstevel@tonic-gatevalues can also be retrieved. 6447*0Sstevel@tonic-gate 6448*0Sstevel@tonic-gateThe cookie and CGI namespaces are separate. If you have a parameter 6449*0Sstevel@tonic-gatenamed 'answers' and a cookie named 'answers', the values retrieved by 6450*0Sstevel@tonic-gateparam() and cookie() are independent of each other. However, it's 6451*0Sstevel@tonic-gatesimple to turn a CGI parameter into a cookie, and vice-versa: 6452*0Sstevel@tonic-gate 6453*0Sstevel@tonic-gate # turn a CGI parameter into a cookie 6454*0Sstevel@tonic-gate $c=$q->cookie(-name=>'answers',-value=>[$q->param('answers')]); 6455*0Sstevel@tonic-gate # vice-versa 6456*0Sstevel@tonic-gate $q->param(-name=>'answers',-value=>[$q->cookie('answers')]); 6457*0Sstevel@tonic-gate 6458*0Sstevel@tonic-gateSee the B<cookie.cgi> example script for some ideas on how to use 6459*0Sstevel@tonic-gatecookies effectively. 6460*0Sstevel@tonic-gate 6461*0Sstevel@tonic-gate=head1 WORKING WITH FRAMES 6462*0Sstevel@tonic-gate 6463*0Sstevel@tonic-gateIt's possible for CGI.pm scripts to write into several browser panels 6464*0Sstevel@tonic-gateand windows using the HTML 4 frame mechanism. There are three 6465*0Sstevel@tonic-gatetechniques for defining new frames programmatically: 6466*0Sstevel@tonic-gate 6467*0Sstevel@tonic-gate=over 4 6468*0Sstevel@tonic-gate 6469*0Sstevel@tonic-gate=item 1. Create a <Frameset> document 6470*0Sstevel@tonic-gate 6471*0Sstevel@tonic-gateAfter writing out the HTTP header, instead of creating a standard 6472*0Sstevel@tonic-gateHTML document using the start_html() call, create a <frameset> 6473*0Sstevel@tonic-gatedocument that defines the frames on the page. Specify your script(s) 6474*0Sstevel@tonic-gate(with appropriate parameters) as the SRC for each of the frames. 6475*0Sstevel@tonic-gate 6476*0Sstevel@tonic-gateThere is no specific support for creating <frameset> sections 6477*0Sstevel@tonic-gatein CGI.pm, but the HTML is very simple to write. See the frame 6478*0Sstevel@tonic-gatedocumentation in Netscape's home pages for details 6479*0Sstevel@tonic-gate 6480*0Sstevel@tonic-gate http://home.netscape.com/assist/net_sites/frames.html 6481*0Sstevel@tonic-gate 6482*0Sstevel@tonic-gate=item 2. Specify the destination for the document in the HTTP header 6483*0Sstevel@tonic-gate 6484*0Sstevel@tonic-gateYou may provide a B<-target> parameter to the header() method: 6485*0Sstevel@tonic-gate 6486*0Sstevel@tonic-gate print $q->header(-target=>'ResultsWindow'); 6487*0Sstevel@tonic-gate 6488*0Sstevel@tonic-gateThis will tell the browser to load the output of your script into the 6489*0Sstevel@tonic-gateframe named "ResultsWindow". If a frame of that name doesn't already 6490*0Sstevel@tonic-gateexist, the browser will pop up a new window and load your script's 6491*0Sstevel@tonic-gatedocument into that. There are a number of magic names that you can 6492*0Sstevel@tonic-gateuse for targets. See the frame documents on Netscape's home pages for 6493*0Sstevel@tonic-gatedetails. 6494*0Sstevel@tonic-gate 6495*0Sstevel@tonic-gate=item 3. Specify the destination for the document in the <form> tag 6496*0Sstevel@tonic-gate 6497*0Sstevel@tonic-gateYou can specify the frame to load in the FORM tag itself. With 6498*0Sstevel@tonic-gateCGI.pm it looks like this: 6499*0Sstevel@tonic-gate 6500*0Sstevel@tonic-gate print $q->start_form(-target=>'ResultsWindow'); 6501*0Sstevel@tonic-gate 6502*0Sstevel@tonic-gateWhen your script is reinvoked by the form, its output will be loaded 6503*0Sstevel@tonic-gateinto the frame named "ResultsWindow". If one doesn't already exist 6504*0Sstevel@tonic-gatea new window will be created. 6505*0Sstevel@tonic-gate 6506*0Sstevel@tonic-gate=back 6507*0Sstevel@tonic-gate 6508*0Sstevel@tonic-gateThe script "frameset.cgi" in the examples directory shows one way to 6509*0Sstevel@tonic-gatecreate pages in which the fill-out form and the response live in 6510*0Sstevel@tonic-gateside-by-side frames. 6511*0Sstevel@tonic-gate 6512*0Sstevel@tonic-gate=head1 LIMITED SUPPORT FOR CASCADING STYLE SHEETS 6513*0Sstevel@tonic-gate 6514*0Sstevel@tonic-gateCGI.pm has limited support for HTML3's cascading style sheets (css). 6515*0Sstevel@tonic-gateTo incorporate a stylesheet into your document, pass the 6516*0Sstevel@tonic-gatestart_html() method a B<-style> parameter. The value of this 6517*0Sstevel@tonic-gateparameter may be a scalar, in which case it is treated as the source 6518*0Sstevel@tonic-gateURL for the stylesheet, or it may be a hash reference. In the latter 6519*0Sstevel@tonic-gatecase you should provide the hash with one or more of B<-src> or 6520*0Sstevel@tonic-gateB<-code>. B<-src> points to a URL where an externally-defined 6521*0Sstevel@tonic-gatestylesheet can be found. B<-code> points to a scalar value to be 6522*0Sstevel@tonic-gateincorporated into a <style> section. Style definitions in B<-code> 6523*0Sstevel@tonic-gateoverride similarly-named ones in B<-src>, hence the name "cascading." 6524*0Sstevel@tonic-gate 6525*0Sstevel@tonic-gateYou may also specify the type of the stylesheet by adding the optional 6526*0Sstevel@tonic-gateB<-type> parameter to the hash pointed to by B<-style>. If not 6527*0Sstevel@tonic-gatespecified, the style defaults to 'text/css'. 6528*0Sstevel@tonic-gate 6529*0Sstevel@tonic-gateTo refer to a style within the body of your document, add the 6530*0Sstevel@tonic-gateB<-class> parameter to any HTML element: 6531*0Sstevel@tonic-gate 6532*0Sstevel@tonic-gate print h1({-class=>'Fancy'},'Welcome to the Party'); 6533*0Sstevel@tonic-gate 6534*0Sstevel@tonic-gateOr define styles on the fly with the B<-style> parameter: 6535*0Sstevel@tonic-gate 6536*0Sstevel@tonic-gate print h1({-style=>'Color: red;'},'Welcome to Hell'); 6537*0Sstevel@tonic-gate 6538*0Sstevel@tonic-gateYou may also use the new B<span()> element to apply a style to a 6539*0Sstevel@tonic-gatesection of text: 6540*0Sstevel@tonic-gate 6541*0Sstevel@tonic-gate print span({-style=>'Color: red;'}, 6542*0Sstevel@tonic-gate h1('Welcome to Hell'), 6543*0Sstevel@tonic-gate "Where did that handbasket get to?" 6544*0Sstevel@tonic-gate ); 6545*0Sstevel@tonic-gate 6546*0Sstevel@tonic-gateNote that you must import the ":html3" definitions to have the 6547*0Sstevel@tonic-gateB<span()> method available. Here's a quick and dirty example of using 6548*0Sstevel@tonic-gateCSS's. See the CSS specification at 6549*0Sstevel@tonic-gatehttp://www.w3.org/pub/WWW/TR/Wd-css-1.html for more information. 6550*0Sstevel@tonic-gate 6551*0Sstevel@tonic-gate use CGI qw/:standard :html3/; 6552*0Sstevel@tonic-gate 6553*0Sstevel@tonic-gate #here's a stylesheet incorporated directly into the page 6554*0Sstevel@tonic-gate $newStyle=<<END; 6555*0Sstevel@tonic-gate <!-- 6556*0Sstevel@tonic-gate P.Tip { 6557*0Sstevel@tonic-gate margin-right: 50pt; 6558*0Sstevel@tonic-gate margin-left: 50pt; 6559*0Sstevel@tonic-gate color: red; 6560*0Sstevel@tonic-gate } 6561*0Sstevel@tonic-gate P.Alert { 6562*0Sstevel@tonic-gate font-size: 30pt; 6563*0Sstevel@tonic-gate font-family: sans-serif; 6564*0Sstevel@tonic-gate color: red; 6565*0Sstevel@tonic-gate } 6566*0Sstevel@tonic-gate --> 6567*0Sstevel@tonic-gate END 6568*0Sstevel@tonic-gate print header(); 6569*0Sstevel@tonic-gate print start_html( -title=>'CGI with Style', 6570*0Sstevel@tonic-gate -style=>{-src=>'http://www.capricorn.com/style/st1.css', 6571*0Sstevel@tonic-gate -code=>$newStyle} 6572*0Sstevel@tonic-gate ); 6573*0Sstevel@tonic-gate print h1('CGI with Style'), 6574*0Sstevel@tonic-gate p({-class=>'Tip'}, 6575*0Sstevel@tonic-gate "Better read the cascading style sheet spec before playing with this!"), 6576*0Sstevel@tonic-gate span({-style=>'color: magenta'}, 6577*0Sstevel@tonic-gate "Look Mom, no hands!", 6578*0Sstevel@tonic-gate p(), 6579*0Sstevel@tonic-gate "Whooo wee!" 6580*0Sstevel@tonic-gate ); 6581*0Sstevel@tonic-gate print end_html; 6582*0Sstevel@tonic-gate 6583*0Sstevel@tonic-gatePass an array reference to B<-style> in order to incorporate multiple 6584*0Sstevel@tonic-gatestylesheets into your document. 6585*0Sstevel@tonic-gate 6586*0Sstevel@tonic-gateShould you wish to incorporate a verbatim stylesheet that includes 6587*0Sstevel@tonic-gatearbitrary formatting in the header, you may pass a -verbatim tag to 6588*0Sstevel@tonic-gatethe -style hash, as follows: 6589*0Sstevel@tonic-gate 6590*0Sstevel@tonic-gateprint $q->start_html (-STYLE => {-verbatim => '@import 6591*0Sstevel@tonic-gateurl("/server-common/css/'.$cssFile.'");', 6592*0Sstevel@tonic-gate -src => '/server-common/css/core.css'}); 6593*0Sstevel@tonic-gate</blockquote></pre> 6594*0Sstevel@tonic-gate 6595*0Sstevel@tonic-gate 6596*0Sstevel@tonic-gateThis will generate an HTML header that contains this: 6597*0Sstevel@tonic-gate 6598*0Sstevel@tonic-gate <link rel="stylesheet" type="text/css" href="/server-common/css/core.css"> 6599*0Sstevel@tonic-gate <style type="text/css"> 6600*0Sstevel@tonic-gate @import url("/server-common/css/main.css"); 6601*0Sstevel@tonic-gate </style> 6602*0Sstevel@tonic-gate 6603*0Sstevel@tonic-gateAny additional arguments passed in the -style value will be 6604*0Sstevel@tonic-gateincorporated into the <link> tag. For example: 6605*0Sstevel@tonic-gate 6606*0Sstevel@tonic-gate start_html(-style=>{-src=>['/styles/print.css','/styles/layout.css'], 6607*0Sstevel@tonic-gate -media => 'all'}); 6608*0Sstevel@tonic-gate 6609*0Sstevel@tonic-gateThis will give: 6610*0Sstevel@tonic-gate 6611*0Sstevel@tonic-gate <link rel="stylesheet" type="text/css" href="/styles/print.css" media="all"/> 6612*0Sstevel@tonic-gate <link rel="stylesheet" type="text/css" href="/styles/layout.css" media="all"/> 6613*0Sstevel@tonic-gate 6614*0Sstevel@tonic-gate<p> 6615*0Sstevel@tonic-gate 6616*0Sstevel@tonic-gateTo make more complicated <link> tags, use the Link() function 6617*0Sstevel@tonic-gateand pass it to start_html() in the -head argument, as in: 6618*0Sstevel@tonic-gate 6619*0Sstevel@tonic-gate @h = (Link({-rel=>'stylesheet',-type=>'text/css',-src=>'/ss/ss.css',-media=>'all'}), 6620*0Sstevel@tonic-gate Link({-rel=>'stylesheet',-type=>'text/css',-src=>'/ss/fred.css',-media=>'paper'})); 6621*0Sstevel@tonic-gate print start_html({-head=>\@h}) 6622*0Sstevel@tonic-gate 6623*0Sstevel@tonic-gate=head1 DEBUGGING 6624*0Sstevel@tonic-gate 6625*0Sstevel@tonic-gateIf you are running the script from the command line or in the perl 6626*0Sstevel@tonic-gatedebugger, you can pass the script a list of keywords or 6627*0Sstevel@tonic-gateparameter=value pairs on the command line or from standard input (you 6628*0Sstevel@tonic-gatedon't have to worry about tricking your script into reading from 6629*0Sstevel@tonic-gateenvironment variables). You can pass keywords like this: 6630*0Sstevel@tonic-gate 6631*0Sstevel@tonic-gate your_script.pl keyword1 keyword2 keyword3 6632*0Sstevel@tonic-gate 6633*0Sstevel@tonic-gateor this: 6634*0Sstevel@tonic-gate 6635*0Sstevel@tonic-gate your_script.pl keyword1+keyword2+keyword3 6636*0Sstevel@tonic-gate 6637*0Sstevel@tonic-gateor this: 6638*0Sstevel@tonic-gate 6639*0Sstevel@tonic-gate your_script.pl name1=value1 name2=value2 6640*0Sstevel@tonic-gate 6641*0Sstevel@tonic-gateor this: 6642*0Sstevel@tonic-gate 6643*0Sstevel@tonic-gate your_script.pl name1=value1&name2=value2 6644*0Sstevel@tonic-gate 6645*0Sstevel@tonic-gateTo turn off this feature, use the -no_debug pragma. 6646*0Sstevel@tonic-gate 6647*0Sstevel@tonic-gateTo test the POST method, you may enable full debugging with the -debug 6648*0Sstevel@tonic-gatepragma. This will allow you to feed newline-delimited name=value 6649*0Sstevel@tonic-gatepairs to the script on standard input. 6650*0Sstevel@tonic-gate 6651*0Sstevel@tonic-gateWhen debugging, you can use quotes and backslashes to escape 6652*0Sstevel@tonic-gatecharacters in the familiar shell manner, letting you place 6653*0Sstevel@tonic-gatespaces and other funny characters in your parameter=value 6654*0Sstevel@tonic-gatepairs: 6655*0Sstevel@tonic-gate 6656*0Sstevel@tonic-gate your_script.pl "name1='I am a long value'" "name2=two\ words" 6657*0Sstevel@tonic-gate 6658*0Sstevel@tonic-gateFinally, you can set the path info for the script by prefixing the first 6659*0Sstevel@tonic-gatename/value parameter with the path followed by a question mark (?): 6660*0Sstevel@tonic-gate 6661*0Sstevel@tonic-gate your_script.pl /your/path/here?name1=value1&name2=value2 6662*0Sstevel@tonic-gate 6663*0Sstevel@tonic-gate=head2 DUMPING OUT ALL THE NAME/VALUE PAIRS 6664*0Sstevel@tonic-gate 6665*0Sstevel@tonic-gateThe Dump() method produces a string consisting of all the query's 6666*0Sstevel@tonic-gatename/value pairs formatted nicely as a nested list. This is useful 6667*0Sstevel@tonic-gatefor debugging purposes: 6668*0Sstevel@tonic-gate 6669*0Sstevel@tonic-gate print $query->Dump 6670*0Sstevel@tonic-gate 6671*0Sstevel@tonic-gate 6672*0Sstevel@tonic-gateProduces something that looks like: 6673*0Sstevel@tonic-gate 6674*0Sstevel@tonic-gate <ul> 6675*0Sstevel@tonic-gate <li>name1 6676*0Sstevel@tonic-gate <ul> 6677*0Sstevel@tonic-gate <li>value1 6678*0Sstevel@tonic-gate <li>value2 6679*0Sstevel@tonic-gate </ul> 6680*0Sstevel@tonic-gate <li>name2 6681*0Sstevel@tonic-gate <ul> 6682*0Sstevel@tonic-gate <li>value1 6683*0Sstevel@tonic-gate </ul> 6684*0Sstevel@tonic-gate </ul> 6685*0Sstevel@tonic-gate 6686*0Sstevel@tonic-gateAs a shortcut, you can interpolate the entire CGI object into a string 6687*0Sstevel@tonic-gateand it will be replaced with the a nice HTML dump shown above: 6688*0Sstevel@tonic-gate 6689*0Sstevel@tonic-gate $query=new CGI; 6690*0Sstevel@tonic-gate print "<h2>Current Values</h2> $query\n"; 6691*0Sstevel@tonic-gate 6692*0Sstevel@tonic-gate=head1 FETCHING ENVIRONMENT VARIABLES 6693*0Sstevel@tonic-gate 6694*0Sstevel@tonic-gateSome of the more useful environment variables can be fetched 6695*0Sstevel@tonic-gatethrough this interface. The methods are as follows: 6696*0Sstevel@tonic-gate 6697*0Sstevel@tonic-gate=over 4 6698*0Sstevel@tonic-gate 6699*0Sstevel@tonic-gate=item B<Accept()> 6700*0Sstevel@tonic-gate 6701*0Sstevel@tonic-gateReturn a list of MIME types that the remote browser accepts. If you 6702*0Sstevel@tonic-gategive this method a single argument corresponding to a MIME type, as in 6703*0Sstevel@tonic-gate$query->Accept('text/html'), it will return a floating point value 6704*0Sstevel@tonic-gatecorresponding to the browser's preference for this type from 0.0 6705*0Sstevel@tonic-gate(don't want) to 1.0. Glob types (e.g. text/*) in the browser's accept 6706*0Sstevel@tonic-gatelist are handled correctly. 6707*0Sstevel@tonic-gate 6708*0Sstevel@tonic-gateNote that the capitalization changed between version 2.43 and 2.44 in 6709*0Sstevel@tonic-gateorder to avoid conflict with Perl's accept() function. 6710*0Sstevel@tonic-gate 6711*0Sstevel@tonic-gate=item B<raw_cookie()> 6712*0Sstevel@tonic-gate 6713*0Sstevel@tonic-gateReturns the HTTP_COOKIE variable, an HTTP extension implemented by 6714*0Sstevel@tonic-gateNetscape browsers version 1.1 and higher, and all versions of Internet 6715*0Sstevel@tonic-gateExplorer. Cookies have a special format, and this method call just 6716*0Sstevel@tonic-gatereturns the raw form (?cookie dough). See cookie() for ways of 6717*0Sstevel@tonic-gatesetting and retrieving cooked cookies. 6718*0Sstevel@tonic-gate 6719*0Sstevel@tonic-gateCalled with no parameters, raw_cookie() returns the packed cookie 6720*0Sstevel@tonic-gatestructure. You can separate it into individual cookies by splitting 6721*0Sstevel@tonic-gateon the character sequence "; ". Called with the name of a cookie, 6722*0Sstevel@tonic-gateretrieves the B<unescaped> form of the cookie. You can use the 6723*0Sstevel@tonic-gateregular cookie() method to get the names, or use the raw_fetch() 6724*0Sstevel@tonic-gatemethod from the CGI::Cookie module. 6725*0Sstevel@tonic-gate 6726*0Sstevel@tonic-gate=item B<user_agent()> 6727*0Sstevel@tonic-gate 6728*0Sstevel@tonic-gateReturns the HTTP_USER_AGENT variable. If you give 6729*0Sstevel@tonic-gatethis method a single argument, it will attempt to 6730*0Sstevel@tonic-gatepattern match on it, allowing you to do something 6731*0Sstevel@tonic-gatelike $query->user_agent(netscape); 6732*0Sstevel@tonic-gate 6733*0Sstevel@tonic-gate=item B<path_info()> 6734*0Sstevel@tonic-gate 6735*0Sstevel@tonic-gateReturns additional path information from the script URL. 6736*0Sstevel@tonic-gateE.G. fetching /cgi-bin/your_script/additional/stuff will result in 6737*0Sstevel@tonic-gate$query->path_info() returning "/additional/stuff". 6738*0Sstevel@tonic-gate 6739*0Sstevel@tonic-gateNOTE: The Microsoft Internet Information Server 6740*0Sstevel@tonic-gateis broken with respect to additional path information. If 6741*0Sstevel@tonic-gateyou use the Perl DLL library, the IIS server will attempt to 6742*0Sstevel@tonic-gateexecute the additional path information as a Perl script. 6743*0Sstevel@tonic-gateIf you use the ordinary file associations mapping, the 6744*0Sstevel@tonic-gatepath information will be present in the environment, 6745*0Sstevel@tonic-gatebut incorrect. The best thing to do is to avoid using additional 6746*0Sstevel@tonic-gatepath information in CGI scripts destined for use with IIS. 6747*0Sstevel@tonic-gate 6748*0Sstevel@tonic-gate=item B<path_translated()> 6749*0Sstevel@tonic-gate 6750*0Sstevel@tonic-gateAs per path_info() but returns the additional 6751*0Sstevel@tonic-gatepath information translated into a physical path, e.g. 6752*0Sstevel@tonic-gate"/usr/local/etc/httpd/htdocs/additional/stuff". 6753*0Sstevel@tonic-gate 6754*0Sstevel@tonic-gateThe Microsoft IIS is broken with respect to the translated 6755*0Sstevel@tonic-gatepath as well. 6756*0Sstevel@tonic-gate 6757*0Sstevel@tonic-gate=item B<remote_host()> 6758*0Sstevel@tonic-gate 6759*0Sstevel@tonic-gateReturns either the remote host name or IP address. 6760*0Sstevel@tonic-gateif the former is unavailable. 6761*0Sstevel@tonic-gate 6762*0Sstevel@tonic-gate=item B<script_name()> 6763*0Sstevel@tonic-gateReturn the script name as a partial URL, for self-refering 6764*0Sstevel@tonic-gatescripts. 6765*0Sstevel@tonic-gate 6766*0Sstevel@tonic-gate=item B<referer()> 6767*0Sstevel@tonic-gate 6768*0Sstevel@tonic-gateReturn the URL of the page the browser was viewing 6769*0Sstevel@tonic-gateprior to fetching your script. Not available for all 6770*0Sstevel@tonic-gatebrowsers. 6771*0Sstevel@tonic-gate 6772*0Sstevel@tonic-gate=item B<auth_type ()> 6773*0Sstevel@tonic-gate 6774*0Sstevel@tonic-gateReturn the authorization/verification method in use for this 6775*0Sstevel@tonic-gatescript, if any. 6776*0Sstevel@tonic-gate 6777*0Sstevel@tonic-gate=item B<server_name ()> 6778*0Sstevel@tonic-gate 6779*0Sstevel@tonic-gateReturns the name of the server, usually the machine's host 6780*0Sstevel@tonic-gatename. 6781*0Sstevel@tonic-gate 6782*0Sstevel@tonic-gate=item B<virtual_host ()> 6783*0Sstevel@tonic-gate 6784*0Sstevel@tonic-gateWhen using virtual hosts, returns the name of the host that 6785*0Sstevel@tonic-gatethe browser attempted to contact 6786*0Sstevel@tonic-gate 6787*0Sstevel@tonic-gate=item B<server_port ()> 6788*0Sstevel@tonic-gate 6789*0Sstevel@tonic-gateReturn the port that the server is listening on. 6790*0Sstevel@tonic-gate 6791*0Sstevel@tonic-gate=item B<virtual_port ()> 6792*0Sstevel@tonic-gate 6793*0Sstevel@tonic-gateLike server_port() except that it takes virtual hosts into account. 6794*0Sstevel@tonic-gateUse this when running with virtual hosts. 6795*0Sstevel@tonic-gate 6796*0Sstevel@tonic-gate=item B<server_software ()> 6797*0Sstevel@tonic-gate 6798*0Sstevel@tonic-gateReturns the server software and version number. 6799*0Sstevel@tonic-gate 6800*0Sstevel@tonic-gate=item B<remote_user ()> 6801*0Sstevel@tonic-gate 6802*0Sstevel@tonic-gateReturn the authorization/verification name used for user 6803*0Sstevel@tonic-gateverification, if this script is protected. 6804*0Sstevel@tonic-gate 6805*0Sstevel@tonic-gate=item B<user_name ()> 6806*0Sstevel@tonic-gate 6807*0Sstevel@tonic-gateAttempt to obtain the remote user's name, using a variety of different 6808*0Sstevel@tonic-gatetechniques. This only works with older browsers such as Mosaic. 6809*0Sstevel@tonic-gateNewer browsers do not report the user name for privacy reasons! 6810*0Sstevel@tonic-gate 6811*0Sstevel@tonic-gate=item B<request_method()> 6812*0Sstevel@tonic-gate 6813*0Sstevel@tonic-gateReturns the method used to access your script, usually 6814*0Sstevel@tonic-gateone of 'POST', 'GET' or 'HEAD'. 6815*0Sstevel@tonic-gate 6816*0Sstevel@tonic-gate=item B<content_type()> 6817*0Sstevel@tonic-gate 6818*0Sstevel@tonic-gateReturns the content_type of data submitted in a POST, generally 6819*0Sstevel@tonic-gatemultipart/form-data or application/x-www-form-urlencoded 6820*0Sstevel@tonic-gate 6821*0Sstevel@tonic-gate=item B<http()> 6822*0Sstevel@tonic-gate 6823*0Sstevel@tonic-gateCalled with no arguments returns the list of HTTP environment 6824*0Sstevel@tonic-gatevariables, including such things as HTTP_USER_AGENT, 6825*0Sstevel@tonic-gateHTTP_ACCEPT_LANGUAGE, and HTTP_ACCEPT_CHARSET, corresponding to the 6826*0Sstevel@tonic-gatelike-named HTTP header fields in the request. Called with the name of 6827*0Sstevel@tonic-gatean HTTP header field, returns its value. Capitalization and the use 6828*0Sstevel@tonic-gateof hyphens versus underscores are not significant. 6829*0Sstevel@tonic-gate 6830*0Sstevel@tonic-gateFor example, all three of these examples are equivalent: 6831*0Sstevel@tonic-gate 6832*0Sstevel@tonic-gate $requested_language = $q->http('Accept-language'); 6833*0Sstevel@tonic-gate $requested_language = $q->http('Accept_language'); 6834*0Sstevel@tonic-gate $requested_language = $q->http('HTTP_ACCEPT_LANGUAGE'); 6835*0Sstevel@tonic-gate 6836*0Sstevel@tonic-gate=item B<https()> 6837*0Sstevel@tonic-gate 6838*0Sstevel@tonic-gateThe same as I<http()>, but operates on the HTTPS environment variables 6839*0Sstevel@tonic-gatepresent when the SSL protocol is in effect. Can be used to determine 6840*0Sstevel@tonic-gatewhether SSL is turned on. 6841*0Sstevel@tonic-gate 6842*0Sstevel@tonic-gate=back 6843*0Sstevel@tonic-gate 6844*0Sstevel@tonic-gate=head1 USING NPH SCRIPTS 6845*0Sstevel@tonic-gate 6846*0Sstevel@tonic-gateNPH, or "no-parsed-header", scripts bypass the server completely by 6847*0Sstevel@tonic-gatesending the complete HTTP header directly to the browser. This has 6848*0Sstevel@tonic-gateslight performance benefits, but is of most use for taking advantage 6849*0Sstevel@tonic-gateof HTTP extensions that are not directly supported by your server, 6850*0Sstevel@tonic-gatesuch as server push and PICS headers. 6851*0Sstevel@tonic-gate 6852*0Sstevel@tonic-gateServers use a variety of conventions for designating CGI scripts as 6853*0Sstevel@tonic-gateNPH. Many Unix servers look at the beginning of the script's name for 6854*0Sstevel@tonic-gatethe prefix "nph-". The Macintosh WebSTAR server and Microsoft's 6855*0Sstevel@tonic-gateInternet Information Server, in contrast, try to decide whether a 6856*0Sstevel@tonic-gateprogram is an NPH script by examining the first line of script output. 6857*0Sstevel@tonic-gate 6858*0Sstevel@tonic-gate 6859*0Sstevel@tonic-gateCGI.pm supports NPH scripts with a special NPH mode. When in this 6860*0Sstevel@tonic-gatemode, CGI.pm will output the necessary extra header information when 6861*0Sstevel@tonic-gatethe header() and redirect() methods are 6862*0Sstevel@tonic-gatecalled. 6863*0Sstevel@tonic-gate 6864*0Sstevel@tonic-gateThe Microsoft Internet Information Server requires NPH mode. As of 6865*0Sstevel@tonic-gateversion 2.30, CGI.pm will automatically detect when the script is 6866*0Sstevel@tonic-gaterunning under IIS and put itself into this mode. You do not need to 6867*0Sstevel@tonic-gatedo this manually, although it won't hurt anything if you do. However, 6868*0Sstevel@tonic-gatenote that if you have applied Service Pack 6, much of the 6869*0Sstevel@tonic-gatefunctionality of NPH scripts, including the ability to redirect while 6870*0Sstevel@tonic-gatesetting a cookie, b<do not work at all> on IIS without a special patch 6871*0Sstevel@tonic-gatefrom Microsoft. See 6872*0Sstevel@tonic-gatehttp://support.microsoft.com/support/kb/articles/Q280/3/41.ASP: 6873*0Sstevel@tonic-gateNon-Parsed Headers Stripped From CGI Applications That Have nph- 6874*0Sstevel@tonic-gatePrefix in Name. 6875*0Sstevel@tonic-gate 6876*0Sstevel@tonic-gate=over 4 6877*0Sstevel@tonic-gate 6878*0Sstevel@tonic-gate=item In the B<use> statement 6879*0Sstevel@tonic-gate 6880*0Sstevel@tonic-gateSimply add the "-nph" pragmato the list of symbols to be imported into 6881*0Sstevel@tonic-gateyour script: 6882*0Sstevel@tonic-gate 6883*0Sstevel@tonic-gate use CGI qw(:standard -nph) 6884*0Sstevel@tonic-gate 6885*0Sstevel@tonic-gate=item By calling the B<nph()> method: 6886*0Sstevel@tonic-gate 6887*0Sstevel@tonic-gateCall B<nph()> with a non-zero parameter at any point after using CGI.pm in your program. 6888*0Sstevel@tonic-gate 6889*0Sstevel@tonic-gate CGI->nph(1) 6890*0Sstevel@tonic-gate 6891*0Sstevel@tonic-gate=item By using B<-nph> parameters 6892*0Sstevel@tonic-gate 6893*0Sstevel@tonic-gatein the B<header()> and B<redirect()> statements: 6894*0Sstevel@tonic-gate 6895*0Sstevel@tonic-gate print $q->header(-nph=>1); 6896*0Sstevel@tonic-gate 6897*0Sstevel@tonic-gate=back 6898*0Sstevel@tonic-gate 6899*0Sstevel@tonic-gate=head1 Server Push 6900*0Sstevel@tonic-gate 6901*0Sstevel@tonic-gateCGI.pm provides four simple functions for producing multipart 6902*0Sstevel@tonic-gatedocuments of the type needed to implement server push. These 6903*0Sstevel@tonic-gatefunctions were graciously provided by Ed Jordan <ed@fidalgo.net>. To 6904*0Sstevel@tonic-gateimport these into your namespace, you must import the ":push" set. 6905*0Sstevel@tonic-gateYou are also advised to put the script into NPH mode and to set $| to 6906*0Sstevel@tonic-gate1 to avoid buffering problems. 6907*0Sstevel@tonic-gate 6908*0Sstevel@tonic-gateHere is a simple script that demonstrates server push: 6909*0Sstevel@tonic-gate 6910*0Sstevel@tonic-gate #!/usr/local/bin/perl 6911*0Sstevel@tonic-gate use CGI qw/:push -nph/; 6912*0Sstevel@tonic-gate $| = 1; 6913*0Sstevel@tonic-gate print multipart_init(-boundary=>'----here we go!'); 6914*0Sstevel@tonic-gate foreach (0 .. 4) { 6915*0Sstevel@tonic-gate print multipart_start(-type=>'text/plain'), 6916*0Sstevel@tonic-gate "The current time is ",scalar(localtime),"\n"; 6917*0Sstevel@tonic-gate if ($_ < 4) { 6918*0Sstevel@tonic-gate print multipart_end; 6919*0Sstevel@tonic-gate } else { 6920*0Sstevel@tonic-gate print multipart_final; 6921*0Sstevel@tonic-gate } 6922*0Sstevel@tonic-gate sleep 1; 6923*0Sstevel@tonic-gate } 6924*0Sstevel@tonic-gate 6925*0Sstevel@tonic-gateThis script initializes server push by calling B<multipart_init()>. 6926*0Sstevel@tonic-gateIt then enters a loop in which it begins a new multipart section by 6927*0Sstevel@tonic-gatecalling B<multipart_start()>, prints the current local time, 6928*0Sstevel@tonic-gateand ends a multipart section with B<multipart_end()>. It then sleeps 6929*0Sstevel@tonic-gatea second, and begins again. On the final iteration, it ends the 6930*0Sstevel@tonic-gatemultipart section with B<multipart_final()> rather than with 6931*0Sstevel@tonic-gateB<multipart_end()>. 6932*0Sstevel@tonic-gate 6933*0Sstevel@tonic-gate=over 4 6934*0Sstevel@tonic-gate 6935*0Sstevel@tonic-gate=item multipart_init() 6936*0Sstevel@tonic-gate 6937*0Sstevel@tonic-gate multipart_init(-boundary=>$boundary); 6938*0Sstevel@tonic-gate 6939*0Sstevel@tonic-gateInitialize the multipart system. The -boundary argument specifies 6940*0Sstevel@tonic-gatewhat MIME boundary string to use to separate parts of the document. 6941*0Sstevel@tonic-gateIf not provided, CGI.pm chooses a reasonable boundary for you. 6942*0Sstevel@tonic-gate 6943*0Sstevel@tonic-gate=item multipart_start() 6944*0Sstevel@tonic-gate 6945*0Sstevel@tonic-gate multipart_start(-type=>$type) 6946*0Sstevel@tonic-gate 6947*0Sstevel@tonic-gateStart a new part of the multipart document using the specified MIME 6948*0Sstevel@tonic-gatetype. If not specified, text/html is assumed. 6949*0Sstevel@tonic-gate 6950*0Sstevel@tonic-gate=item multipart_end() 6951*0Sstevel@tonic-gate 6952*0Sstevel@tonic-gate multipart_end() 6953*0Sstevel@tonic-gate 6954*0Sstevel@tonic-gateEnd a part. You must remember to call multipart_end() once for each 6955*0Sstevel@tonic-gatemultipart_start(), except at the end of the last part of the multipart 6956*0Sstevel@tonic-gatedocument when multipart_final() should be called instead of multipart_end(). 6957*0Sstevel@tonic-gate 6958*0Sstevel@tonic-gate=item multipart_final() 6959*0Sstevel@tonic-gate 6960*0Sstevel@tonic-gate multipart_final() 6961*0Sstevel@tonic-gate 6962*0Sstevel@tonic-gateEnd all parts. You should call multipart_final() rather than 6963*0Sstevel@tonic-gatemultipart_end() at the end of the last part of the multipart document. 6964*0Sstevel@tonic-gate 6965*0Sstevel@tonic-gate=back 6966*0Sstevel@tonic-gate 6967*0Sstevel@tonic-gateUsers interested in server push applications should also have a look 6968*0Sstevel@tonic-gateat the CGI::Push module. 6969*0Sstevel@tonic-gate 6970*0Sstevel@tonic-gateOnly Netscape Navigator supports server push. Internet Explorer 6971*0Sstevel@tonic-gatebrowsers do not. 6972*0Sstevel@tonic-gate 6973*0Sstevel@tonic-gate=head1 Avoiding Denial of Service Attacks 6974*0Sstevel@tonic-gate 6975*0Sstevel@tonic-gateA potential problem with CGI.pm is that, by default, it attempts to 6976*0Sstevel@tonic-gateprocess form POSTings no matter how large they are. A wily hacker 6977*0Sstevel@tonic-gatecould attack your site by sending a CGI script a huge POST of many 6978*0Sstevel@tonic-gatemegabytes. CGI.pm will attempt to read the entire POST into a 6979*0Sstevel@tonic-gatevariable, growing hugely in size until it runs out of memory. While 6980*0Sstevel@tonic-gatethe script attempts to allocate the memory the system may slow down 6981*0Sstevel@tonic-gatedramatically. This is a form of denial of service attack. 6982*0Sstevel@tonic-gate 6983*0Sstevel@tonic-gateAnother possible attack is for the remote user to force CGI.pm to 6984*0Sstevel@tonic-gateaccept a huge file upload. CGI.pm will accept the upload and store it 6985*0Sstevel@tonic-gatein a temporary directory even if your script doesn't expect to receive 6986*0Sstevel@tonic-gatean uploaded file. CGI.pm will delete the file automatically when it 6987*0Sstevel@tonic-gateterminates, but in the meantime the remote user may have filled up the 6988*0Sstevel@tonic-gateserver's disk space, causing problems for other programs. 6989*0Sstevel@tonic-gate 6990*0Sstevel@tonic-gateThe best way to avoid denial of service attacks is to limit the amount 6991*0Sstevel@tonic-gateof memory, CPU time and disk space that CGI scripts can use. Some Web 6992*0Sstevel@tonic-gateservers come with built-in facilities to accomplish this. In other 6993*0Sstevel@tonic-gatecases, you can use the shell I<limit> or I<ulimit> 6994*0Sstevel@tonic-gatecommands to put ceilings on CGI resource usage. 6995*0Sstevel@tonic-gate 6996*0Sstevel@tonic-gate 6997*0Sstevel@tonic-gateCGI.pm also has some simple built-in protections against denial of 6998*0Sstevel@tonic-gateservice attacks, but you must activate them before you can use them. 6999*0Sstevel@tonic-gateThese take the form of two global variables in the CGI name space: 7000*0Sstevel@tonic-gate 7001*0Sstevel@tonic-gate=over 4 7002*0Sstevel@tonic-gate 7003*0Sstevel@tonic-gate=item B<$CGI::POST_MAX> 7004*0Sstevel@tonic-gate 7005*0Sstevel@tonic-gateIf set to a non-negative integer, this variable puts a ceiling 7006*0Sstevel@tonic-gateon the size of POSTings, in bytes. If CGI.pm detects a POST 7007*0Sstevel@tonic-gatethat is greater than the ceiling, it will immediately exit with an error 7008*0Sstevel@tonic-gatemessage. This value will affect both ordinary POSTs and 7009*0Sstevel@tonic-gatemultipart POSTs, meaning that it limits the maximum size of file 7010*0Sstevel@tonic-gateuploads as well. You should set this to a reasonably high 7011*0Sstevel@tonic-gatevalue, such as 1 megabyte. 7012*0Sstevel@tonic-gate 7013*0Sstevel@tonic-gate=item B<$CGI::DISABLE_UPLOADS> 7014*0Sstevel@tonic-gate 7015*0Sstevel@tonic-gateIf set to a non-zero value, this will disable file uploads 7016*0Sstevel@tonic-gatecompletely. Other fill-out form values will work as usual. 7017*0Sstevel@tonic-gate 7018*0Sstevel@tonic-gate=back 7019*0Sstevel@tonic-gate 7020*0Sstevel@tonic-gateYou can use these variables in either of two ways. 7021*0Sstevel@tonic-gate 7022*0Sstevel@tonic-gate=over 4 7023*0Sstevel@tonic-gate 7024*0Sstevel@tonic-gate=item B<1. On a script-by-script basis> 7025*0Sstevel@tonic-gate 7026*0Sstevel@tonic-gateSet the variable at the top of the script, right after the "use" statement: 7027*0Sstevel@tonic-gate 7028*0Sstevel@tonic-gate use CGI qw/:standard/; 7029*0Sstevel@tonic-gate use CGI::Carp 'fatalsToBrowser'; 7030*0Sstevel@tonic-gate $CGI::POST_MAX=1024 * 100; # max 100K posts 7031*0Sstevel@tonic-gate $CGI::DISABLE_UPLOADS = 1; # no uploads 7032*0Sstevel@tonic-gate 7033*0Sstevel@tonic-gate=item B<2. Globally for all scripts> 7034*0Sstevel@tonic-gate 7035*0Sstevel@tonic-gateOpen up CGI.pm, find the definitions for $POST_MAX and 7036*0Sstevel@tonic-gate$DISABLE_UPLOADS, and set them to the desired values. You'll 7037*0Sstevel@tonic-gatefind them towards the top of the file in a subroutine named 7038*0Sstevel@tonic-gateinitialize_globals(). 7039*0Sstevel@tonic-gate 7040*0Sstevel@tonic-gate=back 7041*0Sstevel@tonic-gate 7042*0Sstevel@tonic-gateAn attempt to send a POST larger than $POST_MAX bytes will cause 7043*0Sstevel@tonic-gateI<param()> to return an empty CGI parameter list. You can test for 7044*0Sstevel@tonic-gatethis event by checking I<cgi_error()>, either after you create the CGI 7045*0Sstevel@tonic-gateobject or, if you are using the function-oriented interface, call 7046*0Sstevel@tonic-gate<param()> for the first time. If the POST was intercepted, then 7047*0Sstevel@tonic-gatecgi_error() will return the message "413 POST too large". 7048*0Sstevel@tonic-gate 7049*0Sstevel@tonic-gateThis error message is actually defined by the HTTP protocol, and is 7050*0Sstevel@tonic-gatedesigned to be returned to the browser as the CGI script's status 7051*0Sstevel@tonic-gate code. For example: 7052*0Sstevel@tonic-gate 7053*0Sstevel@tonic-gate $uploaded_file = param('upload'); 7054*0Sstevel@tonic-gate if (!$uploaded_file && cgi_error()) { 7055*0Sstevel@tonic-gate print header(-status=>cgi_error()); 7056*0Sstevel@tonic-gate exit 0; 7057*0Sstevel@tonic-gate } 7058*0Sstevel@tonic-gate 7059*0Sstevel@tonic-gateHowever it isn't clear that any browser currently knows what to do 7060*0Sstevel@tonic-gatewith this status code. It might be better just to create an 7061*0Sstevel@tonic-gateHTML page that warns the user of the problem. 7062*0Sstevel@tonic-gate 7063*0Sstevel@tonic-gate=head1 COMPATIBILITY WITH CGI-LIB.PL 7064*0Sstevel@tonic-gate 7065*0Sstevel@tonic-gateTo make it easier to port existing programs that use cgi-lib.pl the 7066*0Sstevel@tonic-gatecompatibility routine "ReadParse" is provided. Porting is simple: 7067*0Sstevel@tonic-gate 7068*0Sstevel@tonic-gateOLD VERSION 7069*0Sstevel@tonic-gate require "cgi-lib.pl"; 7070*0Sstevel@tonic-gate &ReadParse; 7071*0Sstevel@tonic-gate print "The value of the antique is $in{antique}.\n"; 7072*0Sstevel@tonic-gate 7073*0Sstevel@tonic-gateNEW VERSION 7074*0Sstevel@tonic-gate use CGI; 7075*0Sstevel@tonic-gate CGI::ReadParse 7076*0Sstevel@tonic-gate print "The value of the antique is $in{antique}.\n"; 7077*0Sstevel@tonic-gate 7078*0Sstevel@tonic-gateCGI.pm's ReadParse() routine creates a tied variable named %in, 7079*0Sstevel@tonic-gatewhich can be accessed to obtain the query variables. Like 7080*0Sstevel@tonic-gateReadParse, you can also provide your own variable. Infrequently 7081*0Sstevel@tonic-gateused features of ReadParse, such as the creation of @in and $in 7082*0Sstevel@tonic-gatevariables, are not supported. 7083*0Sstevel@tonic-gate 7084*0Sstevel@tonic-gateOnce you use ReadParse, you can retrieve the query object itself 7085*0Sstevel@tonic-gatethis way: 7086*0Sstevel@tonic-gate 7087*0Sstevel@tonic-gate $q = $in{CGI}; 7088*0Sstevel@tonic-gate print $q->textfield(-name=>'wow', 7089*0Sstevel@tonic-gate -value=>'does this really work?'); 7090*0Sstevel@tonic-gate 7091*0Sstevel@tonic-gateThis allows you to start using the more interesting features 7092*0Sstevel@tonic-gateof CGI.pm without rewriting your old scripts from scratch. 7093*0Sstevel@tonic-gate 7094*0Sstevel@tonic-gate=head1 AUTHOR INFORMATION 7095*0Sstevel@tonic-gate 7096*0Sstevel@tonic-gateCopyright 1995-1998, Lincoln D. Stein. All rights reserved. 7097*0Sstevel@tonic-gate 7098*0Sstevel@tonic-gateThis library is free software; you can redistribute it and/or modify 7099*0Sstevel@tonic-gateit under the same terms as Perl itself. 7100*0Sstevel@tonic-gate 7101*0Sstevel@tonic-gateAddress bug reports and comments to: lstein@cshl.org. When sending 7102*0Sstevel@tonic-gatebug reports, please provide the version of CGI.pm, the version of 7103*0Sstevel@tonic-gatePerl, the name and version of your Web server, and the name and 7104*0Sstevel@tonic-gateversion of the operating system you are using. If the problem is even 7105*0Sstevel@tonic-gateremotely browser dependent, please provide information about the 7106*0Sstevel@tonic-gateaffected browers as well. 7107*0Sstevel@tonic-gate 7108*0Sstevel@tonic-gate=head1 CREDITS 7109*0Sstevel@tonic-gate 7110*0Sstevel@tonic-gateThanks very much to: 7111*0Sstevel@tonic-gate 7112*0Sstevel@tonic-gate=over 4 7113*0Sstevel@tonic-gate 7114*0Sstevel@tonic-gate=item Matt Heffron (heffron@falstaff.css.beckman.com) 7115*0Sstevel@tonic-gate 7116*0Sstevel@tonic-gate=item James Taylor (james.taylor@srs.gov) 7117*0Sstevel@tonic-gate 7118*0Sstevel@tonic-gate=item Scott Anguish <sanguish@digifix.com> 7119*0Sstevel@tonic-gate 7120*0Sstevel@tonic-gate=item Mike Jewell (mlj3u@virginia.edu) 7121*0Sstevel@tonic-gate 7122*0Sstevel@tonic-gate=item Timothy Shimmin (tes@kbs.citri.edu.au) 7123*0Sstevel@tonic-gate 7124*0Sstevel@tonic-gate=item Joergen Haegg (jh@axis.se) 7125*0Sstevel@tonic-gate 7126*0Sstevel@tonic-gate=item Laurent Delfosse (delfosse@delfosse.com) 7127*0Sstevel@tonic-gate 7128*0Sstevel@tonic-gate=item Richard Resnick (applepi1@aol.com) 7129*0Sstevel@tonic-gate 7130*0Sstevel@tonic-gate=item Craig Bishop (csb@barwonwater.vic.gov.au) 7131*0Sstevel@tonic-gate 7132*0Sstevel@tonic-gate=item Tony Curtis (tc@vcpc.univie.ac.at) 7133*0Sstevel@tonic-gate 7134*0Sstevel@tonic-gate=item Tim Bunce (Tim.Bunce@ig.co.uk) 7135*0Sstevel@tonic-gate 7136*0Sstevel@tonic-gate=item Tom Christiansen (tchrist@convex.com) 7137*0Sstevel@tonic-gate 7138*0Sstevel@tonic-gate=item Andreas Koenig (k@franz.ww.TU-Berlin.DE) 7139*0Sstevel@tonic-gate 7140*0Sstevel@tonic-gate=item Tim MacKenzie (Tim.MacKenzie@fulcrum.com.au) 7141*0Sstevel@tonic-gate 7142*0Sstevel@tonic-gate=item Kevin B. Hendricks (kbhend@dogwood.tyler.wm.edu) 7143*0Sstevel@tonic-gate 7144*0Sstevel@tonic-gate=item Stephen Dahmen (joyfire@inxpress.net) 7145*0Sstevel@tonic-gate 7146*0Sstevel@tonic-gate=item Ed Jordan (ed@fidalgo.net) 7147*0Sstevel@tonic-gate 7148*0Sstevel@tonic-gate=item David Alan Pisoni (david@cnation.com) 7149*0Sstevel@tonic-gate 7150*0Sstevel@tonic-gate=item Doug MacEachern (dougm@opengroup.org) 7151*0Sstevel@tonic-gate 7152*0Sstevel@tonic-gate=item Robin Houston (robin@oneworld.org) 7153*0Sstevel@tonic-gate 7154*0Sstevel@tonic-gate=item ...and many many more... 7155*0Sstevel@tonic-gate 7156*0Sstevel@tonic-gatefor suggestions and bug fixes. 7157*0Sstevel@tonic-gate 7158*0Sstevel@tonic-gate=back 7159*0Sstevel@tonic-gate 7160*0Sstevel@tonic-gate=head1 A COMPLETE EXAMPLE OF A SIMPLE FORM-BASED SCRIPT 7161*0Sstevel@tonic-gate 7162*0Sstevel@tonic-gate 7163*0Sstevel@tonic-gate #!/usr/local/bin/perl 7164*0Sstevel@tonic-gate 7165*0Sstevel@tonic-gate use CGI; 7166*0Sstevel@tonic-gate 7167*0Sstevel@tonic-gate $query = new CGI; 7168*0Sstevel@tonic-gate 7169*0Sstevel@tonic-gate print $query->header; 7170*0Sstevel@tonic-gate print $query->start_html("Example CGI.pm Form"); 7171*0Sstevel@tonic-gate print "<h1> Example CGI.pm Form</h1>\n"; 7172*0Sstevel@tonic-gate &print_prompt($query); 7173*0Sstevel@tonic-gate &do_work($query); 7174*0Sstevel@tonic-gate &print_tail; 7175*0Sstevel@tonic-gate print $query->end_html; 7176*0Sstevel@tonic-gate 7177*0Sstevel@tonic-gate sub print_prompt { 7178*0Sstevel@tonic-gate my($query) = @_; 7179*0Sstevel@tonic-gate 7180*0Sstevel@tonic-gate print $query->start_form; 7181*0Sstevel@tonic-gate print "<em>What's your name?</em><br>"; 7182*0Sstevel@tonic-gate print $query->textfield('name'); 7183*0Sstevel@tonic-gate print $query->checkbox('Not my real name'); 7184*0Sstevel@tonic-gate 7185*0Sstevel@tonic-gate print "<p><em>Where can you find English Sparrows?</em><br>"; 7186*0Sstevel@tonic-gate print $query->checkbox_group( 7187*0Sstevel@tonic-gate -name=>'Sparrow locations', 7188*0Sstevel@tonic-gate -values=>[England,France,Spain,Asia,Hoboken], 7189*0Sstevel@tonic-gate -linebreak=>'yes', 7190*0Sstevel@tonic-gate -defaults=>[England,Asia]); 7191*0Sstevel@tonic-gate 7192*0Sstevel@tonic-gate print "<p><em>How far can they fly?</em><br>", 7193*0Sstevel@tonic-gate $query->radio_group( 7194*0Sstevel@tonic-gate -name=>'how far', 7195*0Sstevel@tonic-gate -values=>['10 ft','1 mile','10 miles','real far'], 7196*0Sstevel@tonic-gate -default=>'1 mile'); 7197*0Sstevel@tonic-gate 7198*0Sstevel@tonic-gate print "<p><em>What's your favorite color?</em> "; 7199*0Sstevel@tonic-gate print $query->popup_menu(-name=>'Color', 7200*0Sstevel@tonic-gate -values=>['black','brown','red','yellow'], 7201*0Sstevel@tonic-gate -default=>'red'); 7202*0Sstevel@tonic-gate 7203*0Sstevel@tonic-gate print $query->hidden('Reference','Monty Python and the Holy Grail'); 7204*0Sstevel@tonic-gate 7205*0Sstevel@tonic-gate print "<p><em>What have you got there?</em><br>"; 7206*0Sstevel@tonic-gate print $query->scrolling_list( 7207*0Sstevel@tonic-gate -name=>'possessions', 7208*0Sstevel@tonic-gate -values=>['A Coconut','A Grail','An Icon', 7209*0Sstevel@tonic-gate 'A Sword','A Ticket'], 7210*0Sstevel@tonic-gate -size=>5, 7211*0Sstevel@tonic-gate -multiple=>'true'); 7212*0Sstevel@tonic-gate 7213*0Sstevel@tonic-gate print "<p><em>Any parting comments?</em><br>"; 7214*0Sstevel@tonic-gate print $query->textarea(-name=>'Comments', 7215*0Sstevel@tonic-gate -rows=>10, 7216*0Sstevel@tonic-gate -columns=>50); 7217*0Sstevel@tonic-gate 7218*0Sstevel@tonic-gate print "<p>",$query->reset; 7219*0Sstevel@tonic-gate print $query->submit('Action','Shout'); 7220*0Sstevel@tonic-gate print $query->submit('Action','Scream'); 7221*0Sstevel@tonic-gate print $query->endform; 7222*0Sstevel@tonic-gate print "<hr>\n"; 7223*0Sstevel@tonic-gate } 7224*0Sstevel@tonic-gate 7225*0Sstevel@tonic-gate sub do_work { 7226*0Sstevel@tonic-gate my($query) = @_; 7227*0Sstevel@tonic-gate my(@values,$key); 7228*0Sstevel@tonic-gate 7229*0Sstevel@tonic-gate print "<h2>Here are the current settings in this form</h2>"; 7230*0Sstevel@tonic-gate 7231*0Sstevel@tonic-gate foreach $key ($query->param) { 7232*0Sstevel@tonic-gate print "<strong>$key</strong> -> "; 7233*0Sstevel@tonic-gate @values = $query->param($key); 7234*0Sstevel@tonic-gate print join(", ",@values),"<br>\n"; 7235*0Sstevel@tonic-gate } 7236*0Sstevel@tonic-gate } 7237*0Sstevel@tonic-gate 7238*0Sstevel@tonic-gate sub print_tail { 7239*0Sstevel@tonic-gate print <<END; 7240*0Sstevel@tonic-gate <hr> 7241*0Sstevel@tonic-gate <address>Lincoln D. Stein</address><br> 7242*0Sstevel@tonic-gate <a href="/">Home Page</a> 7243*0Sstevel@tonic-gate END 7244*0Sstevel@tonic-gate } 7245*0Sstevel@tonic-gate 7246*0Sstevel@tonic-gate=head1 BUGS 7247*0Sstevel@tonic-gate 7248*0Sstevel@tonic-gatePlease report them. 7249*0Sstevel@tonic-gate 7250*0Sstevel@tonic-gate=head1 SEE ALSO 7251*0Sstevel@tonic-gate 7252*0Sstevel@tonic-gateL<CGI::Carp>, L<CGI::Fast>, L<CGI::Pretty> 7253*0Sstevel@tonic-gate 7254*0Sstevel@tonic-gate=cut 7255*0Sstevel@tonic-gate 7256