diff options
author | Nicholas Clark <nick@ccl4.org> | 2009-10-01 14:21:16 +0100 |
---|---|---|
committer | Nicholas Clark <nick@ccl4.org> | 2009-10-01 14:21:16 +0100 |
commit | e9dc4a2bf6ff50c27a5bd2e83ff4755923a33e7a (patch) | |
tree | 47d916204681e691f7c15002f5ad25fd8489d10e /ext | |
parent | 3fe7d1fbbb0f3821a413b2c6d13fa8821c6230d3 (diff) | |
download | perl-e9dc4a2bf6ff50c27a5bd2e83ff4755923a33e7a.tar.gz |
Move CGI from ext/ to cpan/
Diffstat (limited to 'ext')
58 files changed, 0 insertions, 15099 deletions
diff --git a/ext/CGI/examples/RunMeFirst b/ext/CGI/examples/RunMeFirst deleted file mode 100755 index 018b11b718..0000000000 --- a/ext/CGI/examples/RunMeFirst +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/local/bin/perl - -# Make a world-writeable directory for saving state. -$ww = 'WORLD_WRITABLE'; -unless (-w $ww) { - $u = umask 0; - mkdir $ww, 0777; - umask $u; -} - -# Decode the sample image. -for $uu (<*.uu>) { - unless (open UU, "<$uu") { warn "Can't open $uu: $!\n"; next } - while (<UU>) { - chomp; - if (/^begin\s+\d+\s+(.+)$/) { - $bin = $1; - last; - } - } - unless (open BIN, "> $bin") { warn "Can't create $bin: $!\n"; next } - binmode BIN; - while (<UU>) { - chomp; - last if /^end/; - print BIN unpack "u", $_; - } - close BIN; - close UU; -} - -# Create symlinks from *.txt to *.cgi for documentation purposes. -foreach (<*.cgi>) { - ($target = $_) =~ s/cgi$/txt/i; - symlink $_, $target unless -e $target; -} diff --git a/ext/CGI/examples/caution.xbm b/ext/CGI/examples/caution.xbm deleted file mode 100644 index 87fcdbef8a..0000000000 --- a/ext/CGI/examples/caution.xbm +++ /dev/null @@ -1,12 +0,0 @@ -#define caution_width 32 -#define caution_height 32 -static char caution_bits[] = { - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x00,0x00,0x00,0x10,0x01, - 0x00,0x00,0x08,0x07,0x00,0x00,0x08,0x0e,0x00,0x00,0x04,0x0e,0x00,0x00,0x04, - 0x1c,0x00,0x00,0x02,0x1c,0x00,0x00,0xe2,0x38,0x00,0x00,0xf1,0x39,0x00,0x00, - 0xf1,0x71,0x00,0x80,0xf0,0x71,0x00,0x80,0xf0,0xe1,0x00,0x40,0xf0,0xe1,0x00, - 0x40,0xf0,0xc1,0x01,0x20,0xf0,0xc1,0x01,0x20,0xf0,0x81,0x03,0x10,0xe0,0x80, - 0x03,0x10,0xe0,0x00,0x07,0x08,0xe0,0x00,0x07,0x08,0xe0,0x00,0x0e,0x04,0x00, - 0x00,0x0e,0x04,0xe0,0x00,0x1c,0x02,0xf0,0x01,0x1c,0x02,0xf0,0x01,0x38,0x01, - 0xe0,0x00,0x38,0x01,0x00,0x00,0x70,0x01,0x00,0x00,0x70,0xff,0xff,0xff,0x7f, - 0xf8,0xff,0xff,0x3f,0x00,0x00,0x00,0x00}; diff --git a/ext/CGI/examples/clickable_image.cgi b/ext/CGI/examples/clickable_image.cgi deleted file mode 100644 index 81daf09690..0000000000 --- a/ext/CGI/examples/clickable_image.cgi +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/local/bin/perl - -use CGI; -$query = new CGI; -print $query->header; -print $query->start_html("A Clickable Image"); -print <<END; -<H1>A Clickable Image</H1> -</A> -END -print "Sorry, this isn't very exciting!\n"; - -print $query->startform; -print $query->image_button('picture',"./wilogo.gif"); -print "Give me a: ",$query->popup_menu('letter',['A','B','C','D','E','W']),"\n"; # -print "<P>Magnification: ",$query->radio_group('magnification',['1X','2X','4X','20X']),"\n"; -print "<HR>\n"; - -if ($query->param) { - print "<P>Magnification, <EM>",$query->param('magnification'),"</EM>\n"; - print "<P>Selected Letter, <EM>",$query->param('letter'),"</EM>\n"; - ($x,$y) = ($query->param('picture.x'),$query->param('picture.y')); - print "<P>Selected Position <EM>($x,$y)</EM>\n"; -} - -print $query->end_html; diff --git a/ext/CGI/examples/cookie.cgi b/ext/CGI/examples/cookie.cgi deleted file mode 100644 index 98adda196e..0000000000 --- a/ext/CGI/examples/cookie.cgi +++ /dev/null @@ -1,88 +0,0 @@ -#!/usr/local/bin/perl - -use CGI qw(:standard); - -@ANIMALS=sort qw/lion tiger bear pig porcupine ferret zebra gnu ostrich - emu moa goat weasel yak chicken sheep hyena dodo lounge-lizard - squirrel rat mouse hedgehog racoon baboon kangaroo hippopotamus - giraffe/; - -# Recover the previous animals from the magic cookie. -# The cookie has been formatted as an associative array -# mapping animal name to the number of animals. -%zoo = cookie('animals'); - -# Recover the new animal(s) from the parameter 'new_animal' -@new = param('new_animals'); - -# If the action is 'add', then add new animals to the zoo. Otherwise -# delete them. -foreach (@new) { - if (param('action') eq 'Add') { - $zoo{$_}++; - } elsif (param('action') eq 'Delete') { - $zoo{$_}-- if $zoo{$_}; - delete $zoo{$_} unless $zoo{$_}; - } -} - -# Add new animals to old, and put them in a cookie -$the_cookie = cookie(-name=>'animals', - -value=>\%zoo, - -expires=>'+1h'); - -# Print the header, incorporating the cookie and the expiration date... -print header(-cookie=>$the_cookie); - -# Now we're ready to create our HTML page. -print start_html('Animal crackers'); - -print <<EOF; -<h1>Animal Crackers</h1> -Choose the animals you want to add to the zoo, and click "add". -Come back to this page any time within the next hour and the list of -animals in the zoo will be resurrected. You can even quit Netscape -completely! -<p> -Try adding the same animal several times to the list. Does this -remind you vaguely of a shopping cart? -<p> -<em>This script only works with Netscape browsers</em> -<p> -<center> -<table border> -<tr><th>Add/Delete<th>Current Contents -EOF - ; - -print "<tr><td>",start_form; -print scrolling_list(-name=>'new_animals', - -values=>[@ANIMALS], - -multiple=>1, - -override=>1, - -size=>10),"<br>"; -print submit(-name=>'action',-value=>'Delete'), - submit(-name=>'action',-value=>'Add'); -print end_form; - -print "<td>"; -if (%zoo) { # make a table - print "<ul>\n"; - foreach (sort keys %zoo) { - print "<li>$zoo{$_} $_\n"; - } - print "</ul>\n"; -} else { - print "<strong>The zoo is empty.</strong>\n"; -} -print "</table></center>"; - -print <<EOF; -<hr> -<ADDRESS>Lincoln D. Stein</ADDRESS><BR> -<A HREF="./">More Examples</A> -EOF - ; -print end_html; - - diff --git a/ext/CGI/examples/crash.cgi b/ext/CGI/examples/crash.cgi deleted file mode 100644 index 64f03c7b3d..0000000000 --- a/ext/CGI/examples/crash.cgi +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/local/bin/perl - -use CGI::Carp qw(fatalsToBrowser); - -# This line invokes a fatal error message at compile time. -foo bar baz; diff --git a/ext/CGI/examples/customize.cgi b/ext/CGI/examples/customize.cgi deleted file mode 100644 index c1c8187514..0000000000 --- a/ext/CGI/examples/customize.cgi +++ /dev/null @@ -1,92 +0,0 @@ -#!/usr/local/bin/perl - -use CGI qw(:standard :html3); - -# Some constants to use in our form. -@colors=qw/aqua black blue fuschia gray green lime maroon navy olive - purple red silver teal white yellow/; -@sizes=("<default>",1..7); - -# recover the "preferences" cookie. -%preferences = cookie('preferences'); - -# If the user wants to change the background color or her -# name, they will appear among our CGI parameters. -foreach ('text','background','name','size') { - $preferences{$_} = param($_) || $preferences{$_}; -} - -# Set some defaults -$preferences{'background'} = $preferences{'background'} || 'silver'; -$preferences{'text'} = $preferences{'text'} || 'black'; - -# Refresh the cookie so that it doesn't expire. This also -# makes any changes the user made permanent. -$the_cookie = cookie(-name=>'preferences', - -value=>\%preferences, - -expires=>'+30d'); -print header(-cookie=>$the_cookie); - -# Adjust the title to incorporate the user's name, if provided. -$title = $preferences{'name'} ? - "Welcome back, $preferences{name}!" : "Customizable Page"; - -# Create the HTML page. We use several of Netscape's -# extended tags to control the background color and the -# font size. It's safe to use Netscape features here because -# cookies don't work anywhere else anyway. -print start_html(-title=>$title, - -bgcolor=>$preferences{'background'}, - -text=>$preferences{'text'} - ); - -print basefont({SIZE=>$preferences{size}}) if $preferences{'size'} > 0; - -print h1($title),<<END; -You can change the appearance of this page by submitting -the fill-out form below. If you return to this page any time -within 30 days, your preferences will be restored. -END - ; - -# Create the form -print hr(), - start_form, - - "Your first name: ", - textfield(-name=>'name', - -default=>$preferences{'name'}, - -size=>30),br, - - table( - TR( - td("Preferred"), - td("Page color:"), - td(popup_menu(-name=>'background', - -values=>\@colors, - -default=>$preferences{'background'}) - ), - ), - TR( - td(''), - td("Text color:"), - td(popup_menu(-name=>'text', - -values=>\@colors, - -default=>$preferences{'text'}) - ) - ), - TR( - td(''), - td("Font size:"), - td(popup_menu(-name=>'size', - -values=>\@sizes, - -default=>$preferences{'size'}) - ) - ) - ), - - submit(-label=>'Set preferences'), - hr; - -print a({HREF=>"/"},'Go to the home page'); -print end_html; diff --git a/ext/CGI/examples/diff_upload.cgi b/ext/CGI/examples/diff_upload.cgi deleted file mode 100644 index 913f9ca179..0000000000 --- a/ext/CGI/examples/diff_upload.cgi +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/local/bin/perl - -$DIFF = "/usr/bin/diff"; -$PERL = "/usr/bin/perl"; - -use CGI qw(:standard); -use CGI::Carp; - -print header; -print start_html("File Diff Example"); -print "<strong>Version </strong>$CGI::VERSION<p>"; - -print <<EOF; -<H1>File Diff Example</H1> -Enter two files. When you press "submit" their diff will be -produced. -EOF - ; - -# Start a multipart form. -print start_multipart_form; -print "File #1:",filefield(-name=>'file1',-size=>45),"<BR>\n"; -print "File #2:",filefield(-name=>'file2',-size=>45),"<BR>\n"; -print "Diff type: ",radio_group(-name=>'type', - -value=>['context','normal']),"<br>\n"; -print reset,submit(-name=>'submit',-value=>'Do Diff'); -print endform; - -# Process the form if there is a file name entered -$file1 = param('file1'); -$file2 = param('file2'); - -$|=1; # for buffering -if ($file1 && $file2) { - $realfile1 = tmpFileName($file1); - $realfile2 = tmpFileName($file2); - print "<HR>\n"; - print "<H2>$file1 vs $file2</H2>\n"; - - print "<PRE>\n"; - $options = "-c" if param('type') eq 'context'; - system "$DIFF $options $realfile1 $realfile2 | $PERL -pe 's/>/>/g; s/</</g;'"; - close $file1; - close $file2; - print "</PRE>\n"; -} - -print <<EOF; -<HR> -<A HREF="../cgi_docs.html">CGI documentation</A> -<HR> -<ADDRESS> -<A HREF="/~lstein">Lincoln D. Stein</A> -</ADDRESS><BR> -Last modified 17 July 1996 -EOF - ; -print end_html; - -sub sanitize { - my $name = shift; - my($safe) = $name=~/([a-zA-Z0-9._~#,]+)/; - unless ($safe) { - print "<strong>$name is not a valid Unix filename -- sorry</strong>"; - exit 0; - } - return $safe; -} diff --git a/ext/CGI/examples/dna_small_gif.uu b/ext/CGI/examples/dna_small_gif.uu deleted file mode 100644 index 1745c73761..0000000000 --- a/ext/CGI/examples/dna_small_gif.uu +++ /dev/null @@ -1,63 +0,0 @@ -begin 444 dna_small.gif -M1TE&.#=A)0`J`.<``+9%&Y<R0M<F'ID\,!<07%<G1:P<0Q`A2Q`P;"L9/L$: -M,"480N5"&RL7:4LD0T,G144[7BHL2B4?3\0I+"</)BQ.9KD0/S878\96$Z\@ -M(:\1*RL:3L0W&QL?2#4?9>@_&A$_5<I"&C`A3*,3-A`//9X<)\@Q(L`@.#\E -M7K,R*R\T6)H++1L72T8=4207:T`G=JX..MD^&!$_;^)2$#T=7S`79AL7.A$3 -M1-=%#^,Q&QT_:C8=1!L86]\R#4M":4H76R,515HZ4"477G@T,J\;(X(@/$\7 -M."4A2N9;$"DZ6RL34-8I$34A73P86I84/\87%1`0/V,B2"0<0N!(%QPH91<6 -M2=!5$3(=73(E23`/,!L4.=$Z'-MH%>`Y#3$=2"=#59M((H88,GP\/]X^&+$R -M$"(79"DF33(93"$86=%;&"T4/=Y"&\\A$Q4Z4!`62*T4-Q4B9+X1*BH96SP? -M1<0D/3(F<-TM$!`=5:H.(!<64C$W?#8J3*`S(S<@3=8V%K$](QT.6Q`43AL4 -M1:$D,;<0,\X9&,8])\@=$A(U244S5U,D6Q<V;]\I&&<K/8!*.R044>=/#YH> -M08$I1B,09S$35R(:4C0?<19$7<D^#Q`>5!()-;4702M`=;56)A`25,0K%"X< -M83`N>K`H'HDS*1`40,M&%!<@7M,_$A<N2L)%%18E4^<M$A@=5=0Q$Q`E311* -M2L8E&2D<7Q\A7P\80B48,%E/8[1-'J4/-"H<3"PA1$,T?Q<15R44,R,A4AL/ -M,^M4%2,07!L+,[\[&!P4520I:C(9.=54$[,2/M-)&RP?7M=(%1$J8<-,%2H@ -M4B,=51436^]2"!X<1A<44RD</>E+#%0>0S0/:4PJ9I,F-6DG420Y<"@09R,0 -M-V$R/R4M<:\H0!(H410Z:AT27&4Q9"L@;=1%(MA-$M5+#RL4+M8Z&AT<7[<: -M(-QA&2,36R$++B(84!0:5ALO:K$A.]X?&!$84V@;/SX<6Q`;2$(B2QD21W4J -M1=TW&@```````````````"P`````)0`J```(_@!]:(N'18\W%15T$1N'C)V? -M0_HH,<$G9YBX!C6<3;+T@AZ-)K@\O*"!KP^$>"KVA`L3*8P3)^5ZA)@B:AH+ -M9];F7.$Q+!`!0=*<E3'5K(:EHS2N%"AP*Y(\&##H6(!A:!XU99B*H?%4IDF? -M!8'<"-F%9I*TH8A83:*TXYD!J83D$0ICI-NE(:O8I6&FJ$64$M5$M%!3PU,F -M2UJD"9I41E824WT2G?BV-!$(!`=,+<IF!P>.%",&P7J"9XB82L5,48F5K,:" -M'94FU='6;!*R3T->E"%&95DR"`/6P,I0PDF)0SG8($$RJN0R`FI(H7$A2]VD -M*^^L_6(T3U*V%XH"_AB:HDS8H$AO5@R:P,8.I%^.:*AC(>Z!'":6RC`1L@W- -M%1Q/,%(.'5+1`<D^74R@P2#?T*'/$"%@\(L5Y?RAB!SO3#*,-6CL44\4]C1# -MR0Q3C&&"!AH08@(#:Y2C@`&1---,.#)\T84=R##`0",H++8#)34,@X80R:"` -M0A<]?'#.!";`TDH.8QBB0354A!,*)WI0\<D\YJRQ3PE[V",(.D#48$T9GO22 -MA0.BC,)'*]3TP,`^\_#QA0P@>`/"*]=<HX\3"C!BAQV%5",$+Z0,0X,UL3SB -M#B[NN$'/,A&,$L,Y[-BASR(@<**("E^,0(<&;[QA0@^,3%",#2S8H,01_LX0 -M`(0:W%`@13#TN+'#&LK@0$T0VER##50*Q/%-%%&H$`0#K7"`!B^X/`),()F0 -M0PNT[K#BRBS1-!("`^=,$8`D="B`QRW?1**+-I?(X$@(L(R2AQ8+Y,*#-*YX -MH(00'1Q!CSI,U'!%)^_%4(X&FUB@01$.@*!#$I?4D48I&1BA!2*HD%))(.+T -MYTEOT3B#PB/U4(,$%QD0(<\QX^CRBC=)@%`!&+:<<TH&M*C1"RJX'-'.'`YX -M<H0@<)#"0CX+I%`*-%:4L@XFS`#[11M?U-))"&RP84LWZL!A1A^YH.*)!)3< -MHXX6L]P3"!I`H/!`*>90`PD.F'3SR@-AG)`&_A=3'"**#[J(P<<I@YCA2@32 -M!,*+Q9H`(XT2'O2RS"CGS.U9!K>0^C0&S/#1""(ZI)'&*6,,$842N%Q!@3NK -M"R'%%4KP0D(Q?"`S!3)<I#!!".68$T(IMHP#>BVE(/$+)#-80<PTLBRP^@$> -M<+,`-[QH$LP+0_P!1C>=S("!,N>8XP<8H6131!B;3`#&#)"DTH(L5#P0S#W+ -MQ)*`$K1HHD4^;E!2QP%:B``&4H$,/Y2C$Y*(1%0(00A)@```77B"*$0@#3>P -MP&PU4`,^H!","P!!$')0P^H6((I5L"$'.;``';[Q!@-\PP"<B$<]EG"(#*C" -M%-(@0":\L0U?D&`#_L50@33.(`4M4``=&4@'+-9!!P9JP`#9T$4H=*$+!#1B -M'3A(`SYH`81'B.,(XJ@"":0(CDRPH@/<"$88V+"%$N#A&)MPX0N2H`L]C&,< -MEW"$%6:0BCV@XPIH>$0?)M$`<92!%OG8Q3#@(`U2C*)%9-!`&`K`!!EP0@80 -M2,0M;I$.:"C#"D.@P#UJ``]GT"*,K%B&*0+!@TFH8VV*0$(:_/`)?7@#'.'0 -M@R[H8``\:&`,=NC"*"B@!2TTHP5]N((TEH&`<)B"!PU`0RQ(P8MNS``9K6@% -M'W31AG%$(BZ2&((PA-&#'I"A&`F8!DD\\`H6-,.,X'B'%,+R#FX4`PS&_L!$ -M.4R0#7W<0@%O2,07$($#9@C3"%C8P!5H88\]J$,"-E!;(.X@C5T<`!65V,40 -M,'&(0C!"`1JP@"3TH`T9=&,5JRC$-]+1`U%TP@@[^,$>Z$&*0%1A%XFK`BFD -MX0L6Y"(#A_A$#[JPC@%\@1@02`(SJ#&&.`A@'\&$!AALX(4Y="`/TA"",UA! -M@%W<8!*\$`$@C%""+G1A"9AP!"<>9@ME*)$0F\C!$I8`B3\TP@%'@$(QH$`" -M)8@#'(B0ACB`P`,@%&,'9"##)S`1!&)\`0)^&,,^+$`("QC"#D\X!":HX0!< -ML(`&-O!%,&H@BS#F0AI'`!LO^"`,/OS!%KJ0_H0HEA`E27Q#%T%X0"%"@`1E -M2,`!:F!%+Q#A!G)40A!HP`4OFK`#-13#`?I(QCW38(Q/9&``%0#!);01BE>$ -M@!TZNL81$G`!-]2!&&5@A1N&T0Q<,$$$%*!``BR1A5$PPPH<74$%]*`#$.RA -M`(VP@#`X$(`7``(%T=@`.5Q`C@:0`P[)D$4'$H`."MB#"908Q=X@,01B9$(7 -MG'A%`#8!"QSL@PUAL,0==M"")CQCP4)0QQUDP806H&,!T]A!`EH@AC2P`P,^ -MT`,*NN%-&&T!&L@X!!Y^<(4.D(,%E>A`,T20C#IXL`6-:,`5F+"#!W"@'%OH -MA`IJ$5(#;`(;AV/'FA103(EV+(,>GHB&&ZJ`!D'<X0[-N$(N@)$+4$C@`<(` -M$(&/<8Q;7$,1UT"``+>P!57`X1F9D`4<W$`"4MP@$ZYX\B-"004Y2$`.HT@% -M)@IAB#><0!]FB(<I.(&`(7P"%GPPQ3)F`0YB0"$0@8"")L!Q!RH`8A&AL,8L -BR!$$,@@#&5OX!1V.\85XA.,.,A##!T2!AP@LXP#;"`@`.P`` -end diff --git a/ext/CGI/examples/file_upload.cgi b/ext/CGI/examples/file_upload.cgi deleted file mode 100644 index 3037de7b14..0000000000 --- a/ext/CGI/examples/file_upload.cgi +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/local/bin/perl -w - -use strict 'refs'; -use lib '..'; -use CGI qw(:standard); -use CGI::Carp qw/fatalsToBrowser/; - -print header(); -print start_html("File Upload Example"); -print strong("Version "),$CGI::VERSION,p; - -print h1("File Upload Example"), - 'This example demonstrates how to prompt the remote user to - select a remote file for uploading. ', - strong("This feature only works with Netscape 2.0 or greater, or IE 4.0 or greater."), - p, - 'Select the ',cite('browser'),' button to choose a text file - to upload. When you press the submit button, this script - will count the number of lines, words, and characters in - the file.'; - -my @types = ('count lines','count words','count characters'); - -# Start a multipart form. -print start_multipart_form(), - "Enter the file to process:", - filefield('filename','',45), - br, - checkbox_group('count',\@types,\@types), - p, - reset,submit('submit','Process File'), - endform; - -# Process the form if there is a file name entered -if (my $file = param('filename')) { - my %stats; - my $tmpfile=tmpFileName($file); - my $mimetype = uploadInfo($file)->{'Content-Type'} || ''; - print hr(), - h2($file), - h3($tmpfile), - h4("MIME Type:",em($mimetype)); - - my($lines,$words,$characters,@words) = (0,0,0,0); - while (<$file>) { - $lines++; - $words += @words=split(/\s+/); - $characters += length($_); - } - close $file; - grep($stats{$_}++,param('count')); - if (%stats) { - print strong("Lines: "),$lines,br if $stats{'count lines'}; - print strong("Words: "),$words,br if $stats{'count words'}; - print strong("Characters: "),$characters,br if $stats{'count characters'}; - } else { - print strong("No statistics selected."); - } -} - -# print cite("URL parameters: "),url_param(); - -print hr(), - a({href=>"../cgi_docs.html"},"CGI documentation"), - hr, - address( - a({href=>'/~lstein'},"Lincoln D. Stein")), - br, - 'Last modified July 17, 1996', - end_html; - diff --git a/ext/CGI/examples/frameset.cgi b/ext/CGI/examples/frameset.cgi deleted file mode 100644 index fc86e92e9a..0000000000 --- a/ext/CGI/examples/frameset.cgi +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/local/bin/perl - -use CGI; -$query = new CGI; -print $query->header; -$TITLE="Frameset Example"; - -# We use the path information to distinguish between calls -# to the script to: -# (1) create the frameset -# (2) create the query form -# (3) create the query response - -$path_info = $query->path_info; - -# If no path information is provided, then we create -# a side-by-side frame set -if (!$path_info) { - &print_frameset; - exit 0; -} - -# If we get here, then we either create the query form -# or we create the response. -&print_html_header; -&print_query if $path_info=~/query/; -&print_response if $path_info=~/response/; -&print_end; - - -# Create the frameset -sub print_frameset { - $script_name = $query->script_name; - print <<EOF; -<html><head><title>$TITLE</title></head> -<frameset cols="50,50"> -<frame src="$script_name/query" name="query"> -<frame src="$script_name/response" name="response"> -</frameset> -EOF - ; - exit 0; -} - -sub print_html_header { - print $query->start_html($TITLE); -} - -sub print_end { - print qq{<P><hr><A HREF="../index.html" TARGET="_top">More Examples</A>}; - print $query->end_html; -} - -sub print_query { - $script_name = $query->script_name; - print "<H1>Frameset Query</H1>\n"; - print $query->startform(-action=>"$script_name/response",-TARGET=>"response"); - print "What's your name? ",$query->textfield('name'); - print "<P>What's the combination?<P>", - $query->checkbox_group(-name=>'words', - -values=>['eenie','meenie','minie','moe']); - - print "<P>What's your favorite color? ", - $query->popup_menu(-name=>'color', - -values=>['red','green','blue','chartreuse']), - "<P>"; - print $query->submit; - print $query->endform; -} - -sub print_response { - print "<H1>Frameset Result</H1>\n"; - unless ($query->param) { - print "<b>No query submitted yet.</b>"; - return; - } - print "Your name is <EM>",$query->param(name),"</EM>\n"; - print "<P>The keywords are: <EM>",join(", ",$query->param(words)),"</EM>\n"; - print "<P>Your favorite color is <EM>",$query->param(color),"</EM>\n"; -} - diff --git a/ext/CGI/examples/index.html b/ext/CGI/examples/index.html deleted file mode 100644 index 133ecc4a16..0000000000 --- a/ext/CGI/examples/index.html +++ /dev/null @@ -1,119 +0,0 @@ -<HTML> <HEAD> -<TITLE>More Examples of Scripts Created with CGI.pm</TITLE> -</HEAD> - -<BODY> -<H1>More Examples of Scripts Created with CGI.pm</H1> - -<H2> Basic Non Sequitur Questionnaire</H2> -<UL> - <LI> <A HREF="tryit.cgi">Try the script</A> - <LI> <A HREF="tryit.txt">Look at its source code</A> -</UL> - -<H2> Advanced Non Sequitur Questionnaire</H2> -<UL> - <LI> <A HREF="monty.cgi">Try the script</A> - <LI> <A HREF="monty.txt">Look at its source code</A> -</UL> - -<H2> Save and restore the state of a form to a file</H2> -<UL> - <LI> <A HREF="save_state.cgi">Try the script</A> - <LI> <A HREF="save_state.txt">Look at its source code</A> -</UL> - -<H2> Server Push</H2> -<ul> - <li><a href="nph-multipart.cgi">Try the script</a> - <li><a href="nph-multipart.txt">Look at its source code</a> -</ul> - -<H2> Read the coordinates from a clickable image map</H2> -<UL> - <LI> <A HREF="clickable_image.cgi">Try the script</A> - <LI> <A HREF="clickable_image.txt">Look at its source code</A> -</UL> - -<H2> Multiple independent forms on the same page</H2> -<UL> - <LI> <A HREF="multiple_forms.cgi">Try the script</A> - <LI> <A HREF="multiple_forms.txt">Look at its source code</A> -</UL> - -<H2> How to maintain state on a page with internal links</H2> -<UL> - <LI> <A HREF="internal_links.cgi">Try the script</A> - <LI> <A HREF="internal_links.txt">Look at its source code</A> -</UL> - -<h2>Echo fatal script errors to the browser</h2> -<em>This script deliberately generates a compile-time error.</em> -<ul> - <li><a href="crash.cgi">Try the script</a> - <li><a href="crash.txt">Look at its source code</a> -</ul> - -<EM>The Following Scripts Work with Netscape Navigator 2.0 and higher, -or Internet Explorer 3.0 and higher</EM> - -<H2> Prompt for a file to upload and process it</H2> -<UL> - <LI> <A HREF="file_upload.cgi">Try the script</A> - <LI> <A HREF="file_upload.txt">Look at its source code</A> -</UL> - -<h2> A Continuously-Updated Page using Server Push</h2> -<ul> - <li><a href="nph-clock.cgi">Try the script</a> - <li><a href="nph-clock.txt">Look at its source code</a> -</ul> - -<h2>Compute the "diff" between two uploaded files</h2> -<ul> - <li><a href="diff_upload.cgi">Try the script</a> - <li><a href="diff_upload.txt">Look at its source code</a> -</ul> - -<h2>Maintain state over a long period with a cookie</h2> -<ul> - <li><a href="cookie.cgi">Try the script</a> - <li><a href="cookie.txt">Look at its source code</a> -</ul> - -<h2>Permanently customize the appearance of a page with a cookie</h2> -<ul> - <li><a href="customize.cgi">Try the script</a> - <li><a href="customize.txt">Look at its source code</a> -</ul> - -<h2> Popup the response in a new window</h2> -<ul> - <li><a href="popup.cgi">Try the script</a> - <li><a href="popup.txt">Look at its source code</a> -</ul> - -<h2> Side-by-side form and response using frames</h2> -<ul> - <li><a href="frameset.cgi">Try the script</a> - <li><a href="frameset.txt">Look at its source code</a> -</ul> - -<h2>Verify the Contents of a fill-out form with JavaScript</h2> -<ul> - <li><a href="javascript.cgi">Try the script</a> - <li><a href="javascript.txt">Look at its source code</a> -</ul> - -<HR> -<MENU> - <LI> <A HREF="../cgi_docs.html">CGI.pm documentation</A> - <LI> <A HREF="../CGI.pm.tar.gz">Download the CGI.pm distribution</A> -</MENU> -<HR> -<ADDRESS>Lincoln D. Stein, lstein@genome.wi.mit.edu<br> -<a href="/">Whitehead Institute/MIT Center for Genome Research</a></ADDRESS> -<!-- hhmts start --> -Last modified: Wed Jun 23 15:31:47 EDT 1999 -<!-- hhmts end --> -</BODY> </HTML> diff --git a/ext/CGI/examples/internal_links.cgi b/ext/CGI/examples/internal_links.cgi deleted file mode 100644 index 4806966842..0000000000 --- a/ext/CGI/examples/internal_links.cgi +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/local/bin/perl - -use CGI; -$query = new CGI; - -# We generate a regular HTML file containing a very long list -# and a popup menu that does nothing except to show that we -# don't lose the state information. -print $query->header; -print $query->start_html("Internal Links Example"); -print "<H1>Internal Links Example</H1>\n"; -print "Click <cite>Submit Query</cite> to create a state. Then scroll down and", - " click on any of the <cite>Jump to top</cite> links. This is not very exciting."; - -print "<A NAME=\"start\"></A>\n"; # an anchor point at the top - -# pick a default starting value; -$query->param('amenu','FOO1') unless $query->param('amenu'); - -print $query->startform; -print $query->popup_menu('amenu',[('FOO1'..'FOO9')]); -print $query->submit,$query->endform; - -# We create a long boring list for the purposes of illustration. -$myself = $query->self_url; -print "<OL>\n"; -for (1..100) { - print qq{<LI>List item #$_ <A HREF="$myself#start">Jump to top</A>\n}; -} -print "</OL>\n"; - -print $query->end_html; - diff --git a/ext/CGI/examples/javascript.cgi b/ext/CGI/examples/javascript.cgi deleted file mode 100644 index 91c2b9e648..0000000000 --- a/ext/CGI/examples/javascript.cgi +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/local/bin/perl - -# This script illustrates how to use JavaScript to validate fill-out -# forms. -use CGI qw(:standard); - -# Here's the javascript code that we include in the document. -$JSCRIPT=<<EOF; - // validate that the user is the right age. Return - // false to prevent the form from being submitted. - function validateForm() { - var today = new Date(); - var birthday = validateDate(document.form1.birthdate); - if (birthday == 0) { - document.form1.birthdate.focus() - document.form1.birthdate.select(); - return false; - } - var milliseconds = today.getTime()-birthday; - var years = milliseconds/(1000 * 60 * 60 * 24 * 365.25); - if ((years > 20) || (years < 5)) { - alert("You must be between the ages of 5 and 20 to submit this form"); - document.form1.birthdate.focus(); - document.form1.birthdate.select(); - return false; - } - // Since we've calculated the age in years already, - // we might as well send it up to our CGI script. - document.form1.age.value=Math.floor(years); - return true; - } - - // make sure that the contents of the supplied - // field contain a valid date. - function validateDate(element) { - var date = Date.parse(element.value); - if (0 == date) { - alert("Please enter date in format MMM DD, YY"); - element.focus(); - element.select(); - } - return date; - } - - // Compliments, compliments - function doPraise(element) { - if (element.checked) { - self.status=element.value + " is an excellent choice!"; - return true; - } else { - return false; - } - } - - function checkColor(element) { - var color = element.options[element.selectedIndex].text; - if (color == "blonde") { - if (confirm("Is it true that blondes have more fun?")) - alert("Darn. That leaves me out."); - } else - alert(color + " is a fine choice!"); - } -EOF - ; - -# here's where the execution begins -print header; -print start_html(-title=>'Personal Profile',-script=>$JSCRIPT); - -print h1("Big Brother Wants to Know All About You"), - strong("Note: "),"This page uses JavaScript and requires ", - "Netscape 2.0 or higher to do anything special."; - -&print_prompt(); -print hr; -&print_response() if param; -print end_html; - -sub print_prompt { - print start_form(-name=>'form1', - -onSubmit=>"return validateForm()"),"\n"; - print "Birthdate (e.g. Jan 3, 1972): ", - textfield(-name=>'birthdate', - -onBlur=>"validateDate(this)"),"<p>\n"; - print "Sex: ",radio_group(-name=>'gender', - -value=>[qw/male female/], - -onClick=>"doPraise(this)"),"<p>\n"; - print "Hair color: ",popup_menu(-name=>'color', - -value=>[qw/brunette blonde red gray/], - -default=>'red', - -onChange=>"checkColor(this)"),"<p>\n"; - print hidden(-name=>'age',-value=>0); - print submit(); - print end_form; -} - -sub print_response { - import_names('Q'); - print h2("Your profile"), - "You claim to be a ",b($Q::age)," year old ",b($Q::color,$Q::gender),".", - "You should be ashamed of yourself for lying so ", - "blatantly to big brother!", - hr; -} - diff --git a/ext/CGI/examples/make_links.pl b/ext/CGI/examples/make_links.pl deleted file mode 100755 index a0aa824556..0000000000 --- a/ext/CGI/examples/make_links.pl +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/local/bin/perl - -# this is just a utility for creating symlinks from *.txt to *.cgi -# for documentation purposes. -foreach (<*.cgi>) { - ($target=$_)=~s/cgi$/txt/; - symlink $_,$target -} diff --git a/ext/CGI/examples/monty.cgi b/ext/CGI/examples/monty.cgi deleted file mode 100644 index 693c2586fc..0000000000 --- a/ext/CGI/examples/monty.cgi +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/local/bin/perl - -use CGI; -use CGI::Carp qw/fatalsToBrowser/; - -$query = new CGI; - -print $query->header; -print $query->start_html("Example CGI.pm Form"); -print "<H1> Example CGI.pm Form</H1>\n"; -&print_prompt($query); -&do_work($query); -&print_tail; -print $query->end_html; - -sub print_prompt { - my($query) = @_; - - print $query->start_form; - print "<EM>What's your name?</EM><BR>"; - print $query->textfield('name'); - print $query->checkbox('Not my real name'); - - print "<P><EM>Where can you find English Sparrows?</EM><BR>"; - print $query->checkbox_group( - -name=>'Sparrow locations', - -Values=>[England,France,Spain,Asia,Hoboken], - -linebreak=>'yes', - -defaults=>[England,Asia]); - - print "<P><EM>How far can they fly?</EM><BR>", - $query->radio_group( - -name=>'how far', - -Values=>['10 ft','1 mile','10 miles','real far'], - -default=>'1 mile'); - - print "<P><EM>What's your favorite color?</EM> "; - print $query->popup_menu(-name=>'Color', - -Values=>['black','brown','red','yellow'], - -default=>'red'); - - print $query->hidden('Reference','Monty Python and the Holy Grail'); - - print "<P><EM>What have you got there?</EM><BR>"; - print $query->scrolling_list( - -name=>'possessions', - -Values=>['A Coconut','A Grail','An Icon', - 'A Sword','A Ticket'], - -size=>5, - -multiple=>'true'); - - print "<P><EM>Any parting comments?</EM><BR>"; - print $query->textarea(-name=>'Comments', - -rows=>10, - -columns=>50); - - print "<P>",$query->reset; - print $query->submit('Action','Shout'); - print $query->submit('Action','Scream'); - print $query->endform; - print "<HR>\n"; - } - -sub do_work { - my($query) = @_; - my(@values,$key); - - print "<H2>Here are the current settings in this form</H2>"; - - foreach $key ($query->param) { - print "<STRONG>$key</STRONG> -> "; - @values = $query->param($key); - print join(", ",@values),"<BR>\n"; - } -} - -sub print_tail { - print <<END; -<HR> -<ADDRESS>Lincoln D. Stein</ADDRESS><BR> -<A HREF="/">Home Page</A> -END - ; -} diff --git a/ext/CGI/examples/multiple_forms.cgi b/ext/CGI/examples/multiple_forms.cgi deleted file mode 100644 index b38bf93e96..0000000000 --- a/ext/CGI/examples/multiple_forms.cgi +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/local/bin/perl - -use CGI; - -$query = new CGI; -print $query->header; -print $query->start_html('Multiple Forms'); -print "<H1>Multiple Forms</H1>\n"; - -# Print the first form -print $query->startform; -$name = $query->remote_user || 'anonymous@' . $query->remote_host; - -print "What's your name? ",$query->textfield('name',$name,50); -print "<P>What's the combination?<P>", - $query->checkbox_group('words',['eenie','meenie','minie','moe']); -print "<P>What's your favorite color? ", - $query->popup_menu('color',['red','green','blue','chartreuse']), - "<P>"; -print $query->submit('form_1','Send Form 1'); -print $query->endform; - -# Print the second form -print "<HR>\n"; -print $query->startform; -print "Some radio buttons: ",$query->radio_group('radio buttons', - [qw{one two three four five}],'three'),"\n"; -print "<P>What's the password? ",$query->password_field('pass','secret'); -print $query->defaults,$query->submit('form_2','Send Form 2'),"\n"; -print $query->endform; - -print "<HR>\n"; - -$query->import_names('Q'); -if ($Q::form_1) { - print "<H2>Form 1 Submitted</H2>\n"; - print "Your name is <EM>$Q::name</EM>\n"; - print "<P>The combination is: <EM>{",join(",",@Q::words),"}</EM>\n"; - print "<P>Your favorite color is <EM>$Q::color</EM>\n"; -} elsif ($Q::form_2) { - print <<EOF; -<H2>Form 2 Submitted</H2> -<P>The value of the radio buttons is <EM>$Q::radio_buttons</EM> -<P>The secret password is <EM>$Q::pass</EM> -EOF - ; -} -print qq{<P><A HREF="./">Other examples</A>}; -print qq{<P><A HREF="../cgi_docs.html">Go to the documentation</A>}; - -print $query->end_html; - - - diff --git a/ext/CGI/examples/nph-clock.cgi b/ext/CGI/examples/nph-clock.cgi deleted file mode 100755 index f34fde27e9..0000000000 --- a/ext/CGI/examples/nph-clock.cgi +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/local/bin/perl -w - -use CGI::Push qw(:standard :html3); - -do_push(-next_page=>\&draw_time,-delay=>1); - -sub draw_time { - my $time = localtime(); - return start_html('Tick Tock'), - div({-align=>CENTER}, - h1('Virtual Clock'), - h2($time) - ), - hr, - a({-href=>'index.html'},'More examples'), - end_html(); -} - diff --git a/ext/CGI/examples/nph-multipart.cgi b/ext/CGI/examples/nph-multipart.cgi deleted file mode 100755 index f8cea59a87..0000000000 --- a/ext/CGI/examples/nph-multipart.cgi +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/local/bin/perl -use CGI qw/:push -nph/; -$| = 1; -print multipart_init(-boundary=>'----------------here we go!'); -while (1) { - print multipart_start(-type=>'text/plain'), - "The current time is ",scalar(localtime),"\n", - multipart_end; - sleep 1; -} diff --git a/ext/CGI/examples/popup.cgi b/ext/CGI/examples/popup.cgi deleted file mode 100644 index 88cea1da9c..0000000000 --- a/ext/CGI/examples/popup.cgi +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/local/bin/perl - -use CGI; -$query = new CGI; -print $query->header; -print $query->start_html('Popup Window'); - - -if (!$query->param) { - print "<H1>Ask your Question</H1>\n"; - print $query->startform(-target=>'_new'); - print "What's your name? ",$query->textfield('name'); - print "<P>What's the combination?<P>", - $query->checkbox_group(-name=>'words', - -values=>['eenie','meenie','minie','moe'], - -defaults=>['eenie','moe']); - - print "<P>What's your favorite color? ", - $query->popup_menu(-name=>'color', - -values=>['red','green','blue','chartreuse']), - "<P>"; - print $query->submit; - print $query->endform; - -} else { - print "<H1>And the Answer is...</H1>\n"; - print "Your name is <EM>",$query->param(name),"</EM>\n"; - print "<P>The keywords are: <EM>",join(", ",$query->param(words)),"</EM>\n"; - print "<P>Your favorite color is <EM>",$query->param(color),"</EM>\n"; -} -print qq{<P><A HREF="cgi_docs.html">Go to the documentation</A>}; -print $query->end_html; diff --git a/ext/CGI/examples/save_state.cgi b/ext/CGI/examples/save_state.cgi deleted file mode 100644 index 85bacaf59a..0000000000 --- a/ext/CGI/examples/save_state.cgi +++ /dev/null @@ -1,67 +0,0 @@ -#!/usr/local/bin/perl - -use CGI; -$query = new CGI; - -print $query->header; -print $query->start_html("Save and Restore Example"); -print "<H1>Save and Restore Example</H1>\n"; - -# Here's where we take action on the previous request -&save_parameters($query) if $query->param('action') eq 'SAVE'; -$query = &restore_parameters($query) if $query->param('action') eq 'RESTORE'; - -# Here's where we create the form -print $query->start_multipart_form; -print "Popup 1: ",$query->popup_menu('popup1',[qw{red green purple magenta orange chartreuse brown}]),"\n"; -print "Popup 2: ",$query->popup_menu('popup2',[qw{lion tiger bear zebra potto wildebeest frog emu gazelle}]),"\n"; -print "<P>"; -$default_name = $query->remote_addr . '.sav'; -print "Save/restore state from file: ",$query->textfield('savefile',$default_name),"\n"; -print "<P>"; -print $query->submit('action','SAVE'),$query->submit('action','RESTORE'); -print "<P>",$query->defaults; -print $query->endform; - -# Here we print out a bit at the end -print $query->end_html; - -sub save_parameters { - local($query) = @_; - local($filename) = &clean_name($query->param('savefile')); - if (open(FILE,">$filename")) { - $query->save(FILE); - close FILE; - print "<STRONG>State has been saved to file $filename</STRONG>\n"; - print "<P>If you remember this name you can restore the state later.\n"; - } else { - print "<STRONG>Error:</STRONG> couldn't write to file $filename: $!\n"; - } -} - -sub restore_parameters { - local($query) = @_; - local($filename) = &clean_name($query->param('savefile')); - if (open(FILE,$filename)) { - $query = new CGI(FILE); # Throw out the old query, replace it with a new one - close FILE; - print "<STRONG>State has been restored from file $filename</STRONG>\n"; - } else { - print "<STRONG>Error:</STRONG> couldn't restore file $filename: $!\n"; - } - return $query; -} - - -# Very important subroutine -- get rid of all the naughty -# metacharacters from the file name. If there are, we -# complain bitterly and die. -sub clean_name { - local($name) = @_; - unless ($name=~/^[\w\._\-]+$/) { - print "<STRONG>$name has naughty characters. Only "; - print "alphanumerics are allowed. You can't use absolute names.</STRONG>"; - die "Attempt to use naughty characters"; - } - return "WORLD_WRITABLE/$name"; -} diff --git a/ext/CGI/examples/tryit.cgi b/ext/CGI/examples/tryit.cgi deleted file mode 100644 index 83c620c3e4..0000000000 --- a/ext/CGI/examples/tryit.cgi +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/local/bin/perl - -use CGI ':standard'; - -print header; -print start_html('A Simple Example'), - h1('A Simple Example'), - start_form, - "What's your name? ",textfield('name'), - p, - "What's the combination?", - p, - checkbox_group(-name=>'words', - -values=>['eenie','meenie','minie','moe'], - -defaults=>['eenie','minie']), - p, - "What's your favorite color? ", - popup_menu(-name=>'color', - -values=>['red','green','blue','chartreuse']), - p, - submit, - end_form, - hr; - -if (param()) { - print - "Your name is: ",em(param('name')), - p, - "The keywords are: ",em(join(", ",param('words'))), - p, - "Your favorite color is: ",em(param('color')), - hr; -} -print a({href=>'../cgi_docs.html'},'Go to the documentation'); -print end_html; - - diff --git a/ext/CGI/examples/wilogo_gif.uu b/ext/CGI/examples/wilogo_gif.uu deleted file mode 100644 index c5d10423b4..0000000000 --- a/ext/CGI/examples/wilogo_gif.uu +++ /dev/null @@ -1,13 +0,0 @@ -begin 444 wilogo.gif -M1TE&.#=A7@!$`(```'X2F?___RP`````7@!$```"_D2.J<#MKF)ZU,A3,[OO -M(IUY']A%9"6AW$F)+#2]Y:BNLF6_\;WMH<?#I72^VP+D"@*)F&"O25KRDM&B -M[%C-7;4_J)*6'4ZE&O`W8"1OQ5UGPWRBIKDPM!MW9J]-[;LUKL;$5W.'YQ3( -M(O<&-^>F*(A55\BX%UEI^;<VB0BH1RFX2=<IELE4^*0'N?-I>OJ8N%(*Z^4G -M.OJJ>8HZ.(>;JRMD><E[!KQHB^3;:APL6Z8\RKPK/)O:*-WLW&7]*\UYR]J) -M?<P=1MR-_6VN76,WGAV^32W^3CZ_SCY3;W__C-R^CU^\%M#T!9PVL(ZZ&>X" -M%A1XSM]!A?T8/C0T$1XMJG\B&G+,"-&C/(VS0(842;`)M'S>_OE8F#"=2S#* -M8LHLAS'D1Y,42UGY9O,F-T:X@@JEE@D1RW>/D@8R.DZ-+*E0CQ:9JJ5JU!SQ -MR&BU2D.;E*4'ER0TNY%G2A/Y.G[=VG%81+5K_UG$21<A6;=YP9'5B++O7:@7 -M\]J5]]?DX7:)%<]5%=B/55>-GQW55;$8L\RW6J8-9>QM7<^A/SMZK!ESY$,+ -(KPA.EJ```#L` -end diff --git a/ext/CGI/lib/CGI.pm b/ext/CGI/lib/CGI.pm deleted file mode 100644 index cacb03a0d1..0000000000 --- a/ext/CGI/lib/CGI.pm +++ /dev/null @@ -1,7970 +0,0 @@ -package CGI; -require 5.004; -use Carp 'croak'; - -# See the bottom of this file for the POD documentation. Search for the -# string '=head'. - -# You can run this file through either pod2man or pod2html to produce pretty -# documentation in manual or html file format (these utilities are part of the -# Perl 5 distribution). - -# Copyright 1995-1998 Lincoln D. Stein. All rights reserved. -# It may be used and modified freely, but I do request that this copyright -# notice remain attached to the file. You may modify this module as you -# wish, but if you redistribute a modified version, please attach a note -# listing the modifications you have made. - -# The most recent version and complete docs are available at: -# http://stein.cshl.org/WWW/software/CGI/ - -$CGI::revision = '$Id: CGI.pm,v 1.266 2009/07/30 16:32:34 lstein Exp $'; -$CGI::VERSION='3.45'; - -# HARD-CODED LOCATION FOR FILE UPLOAD TEMPORARY FILES. -# UNCOMMENT THIS ONLY IF YOU KNOW WHAT YOU'RE DOING. -# $CGITempFile::TMPDIRECTORY = '/usr/tmp'; -use CGI::Util qw(rearrange rearrange_header make_attributes unescape escape expires ebcdic2ascii ascii2ebcdic); - -#use constant XHTML_DTD => ['-//W3C//DTD XHTML Basic 1.0//EN', -# 'http://www.w3.org/TR/xhtml-basic/xhtml-basic10.dtd']; - -use constant XHTML_DTD => ['-//W3C//DTD XHTML 1.0 Transitional//EN', - 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd']; - -{ - local $^W = 0; - $TAINTED = substr("$0$^X",0,0); -} - -$MOD_PERL = 0; # no mod_perl by default - -#global settings -$POST_MAX = -1; # no limit to uploaded files -$DISABLE_UPLOADS = 0; - -@SAVED_SYMBOLS = (); - - -# >>>>> Here are some globals that you might want to adjust <<<<<< -sub initialize_globals { - # Set this to 1 to enable copious autoloader debugging messages - $AUTOLOAD_DEBUG = 0; - - # Set this to 1 to generate XTML-compatible output - $XHTML = 1; - - # Change this to the preferred DTD to print in start_html() - # or use default_dtd('text of DTD to use'); - $DEFAULT_DTD = [ '-//W3C//DTD HTML 4.01 Transitional//EN', - 'http://www.w3.org/TR/html4/loose.dtd' ] ; - - # Set this to 1 to enable NOSTICKY scripts - # or: - # 1) use CGI '-nosticky'; - # 2) $CGI::NOSTICKY = 1; - $NOSTICKY = 0; - - # Set this to 1 to enable NPH scripts - # or: - # 1) use CGI qw(-nph) - # 2) CGI::nph(1) - # 3) print header(-nph=>1) - $NPH = 0; - - # Set this to 1 to enable debugging from @ARGV - # Set to 2 to enable debugging from STDIN - $DEBUG = 1; - - # Set this to 1 to make the temporary files created - # during file uploads safe from prying eyes - # or do... - # 1) use CGI qw(:private_tempfiles) - # 2) CGI::private_tempfiles(1); - $PRIVATE_TEMPFILES = 0; - - # Set this to 1 to generate automatic tab indexes - $TABINDEX = 0; - - # Set this to 1 to cause files uploaded in multipart documents - # to be closed, instead of caching the file handle - # or: - # 1) use CGI qw(:close_upload_files) - # 2) $CGI::close_upload_files(1); - # Uploads with many files run out of file handles. - # Also, for performance, since the file is already on disk, - # it can just be renamed, instead of read and written. - $CLOSE_UPLOAD_FILES = 0; - - # Automatically determined -- don't change - $EBCDIC = 0; - - # Change this to 1 to suppress redundant HTTP headers - $HEADERS_ONCE = 0; - - # separate the name=value pairs by semicolons rather than ampersands - $USE_PARAM_SEMICOLONS = 1; - - # Do not include undefined params parsed from query string - # use CGI qw(-no_undef_params); - $NO_UNDEF_PARAMS = 0; - - # return everything as utf-8 - $PARAM_UTF8 = 0; - - # Other globals that you shouldn't worry about. - undef $Q; - $BEEN_THERE = 0; - $DTD_PUBLIC_IDENTIFIER = ""; - undef @QUERY_PARAM; - undef %EXPORT; - undef $QUERY_CHARSET; - undef %QUERY_FIELDNAMES; - undef %QUERY_TMPFILES; - - # prevent complaints by mod_perl - 1; -} - -# ------------------ START OF THE LIBRARY ------------ - -*end_form = \&endform; - -# make mod_perlhappy -initialize_globals(); - -# FIGURE OUT THE OS WE'RE RUNNING UNDER -# Some systems support the $^O variable. If not -# available then require() the Config library -unless ($OS) { - unless ($OS = $^O) { - require Config; - $OS = $Config::Config{'osname'}; - } -} -if ($OS =~ /^MSWin/i) { - $OS = 'WINDOWS'; -} elsif ($OS =~ /^VMS/i) { - $OS = 'VMS'; -} elsif ($OS =~ /^dos/i) { - $OS = 'DOS'; -} elsif ($OS =~ /^MacOS/i) { - $OS = 'MACINTOSH'; -} elsif ($OS =~ /^os2/i) { - $OS = 'OS2'; -} elsif ($OS =~ /^epoc/i) { - $OS = 'EPOC'; -} elsif ($OS =~ /^cygwin/i) { - $OS = 'CYGWIN'; -} elsif ($OS =~ /^NetWare/i) { - $OS = 'NETWARE'; -} else { - $OS = 'UNIX'; -} - -# Some OS logic. Binary mode enabled on DOS, NT and VMS -$needs_binmode = $OS=~/^(WINDOWS|DOS|OS2|MSWin|CYGWIN|NETWARE)/; - -# This is the default class for the CGI object to use when all else fails. -$DefaultClass = 'CGI' unless defined $CGI::DefaultClass; - -# This is where to look for autoloaded routines. -$AutoloadClass = $DefaultClass unless defined $CGI::AutoloadClass; - -# The path separator is a slash, backslash or semicolon, depending -# on the paltform. -$SL = { - UNIX => '/', OS2 => '\\', EPOC => '/', CYGWIN => '/', NETWARE => '/', - WINDOWS => '\\', DOS => '\\', MACINTOSH => ':', VMS => '/' - }->{$OS}; - -# This no longer seems to be necessary -# Turn on NPH scripts by default when running under IIS server! -# $NPH++ if defined($ENV{'SERVER_SOFTWARE'}) && $ENV{'SERVER_SOFTWARE'}=~/IIS/; -$IIS++ if defined($ENV{'SERVER_SOFTWARE'}) && $ENV{'SERVER_SOFTWARE'}=~/IIS/; - -# Turn on special checking for ActiveState's PerlEx -$PERLEX++ if defined($ENV{'GATEWAY_INTERFACE'}) && $ENV{'GATEWAY_INTERFACE'} =~ /^CGI-PerlEx/; - -# Turn on special checking for Doug MacEachern's modperl -# PerlEx::DBI tries to fool DBI by setting MOD_PERL -if (exists $ENV{MOD_PERL} && ! $PERLEX) { - # mod_perl handlers may run system() on scripts using CGI.pm; - # Make sure so we don't get fooled by inherited $ENV{MOD_PERL} - if (exists $ENV{MOD_PERL_API_VERSION} && $ENV{MOD_PERL_API_VERSION} == 2) { - $MOD_PERL = 2; - require Apache2::Response; - require Apache2::RequestRec; - require Apache2::RequestUtil; - require Apache2::RequestIO; - require APR::Pool; - } else { - $MOD_PERL = 1; - require Apache; - } -} - -# Define the CRLF sequence. I can't use a simple "\r\n" because the meaning -# of "\n" is different on different OS's (sometimes it generates CRLF, sometimes LF -# and sometimes CR). The most popular VMS web server -# doesn't accept CRLF -- instead it wants a LR. EBCDIC machines don't -# use ASCII, so \015\012 means something different. I find this all -# really annoying. -$EBCDIC = "\t" ne "\011"; -if ($OS eq 'VMS') { - $CRLF = "\n"; -} elsif ($EBCDIC) { - $CRLF= "\r\n"; -} else { - $CRLF = "\015\012"; -} - -if ($needs_binmode) { - $CGI::DefaultClass->binmode(\*main::STDOUT); - $CGI::DefaultClass->binmode(\*main::STDIN); - $CGI::DefaultClass->binmode(\*main::STDERR); -} - -%EXPORT_TAGS = ( - ':html2'=>['h1'..'h6',qw/p br hr ol ul li dl dt dd menu code var strong em - tt u i b blockquote pre img a address cite samp dfn html head - base body Link nextid title meta kbd start_html end_html - input Select option comment charset escapeHTML/], - ':html3'=>[qw/div table caption th td TR Tr sup Sub strike applet Param nobr - embed basefont style span layer ilayer font frameset frame script small big Area Map/], - ':html4'=>[qw/abbr acronym bdo col colgroup del fieldset iframe - ins label legend noframes noscript object optgroup Q - thead tbody tfoot/], - ':netscape'=>[qw/blink fontsize center/], - ':form'=>[qw/textfield textarea filefield password_field hidden checkbox checkbox_group - submit reset defaults radio_group popup_menu button autoEscape - scrolling_list image_button start_form end_form startform endform - start_multipart_form end_multipart_form isindex tmpFileName uploadInfo URL_ENCODED MULTIPART/], - ':cgi'=>[qw/param upload path_info path_translated request_uri url self_url script_name - cookie Dump - raw_cookie request_method query_string Accept user_agent remote_host content_type - remote_addr referer server_name server_software server_port server_protocol virtual_port - virtual_host remote_ident auth_type http append - save_parameters restore_parameters param_fetch - remote_user user_name header redirect import_names put - Delete Delete_all url_param cgi_error/], - ':ssl' => [qw/https/], - ':cgi-lib' => [qw/ReadParse PrintHeader HtmlTop HtmlBot SplitParam Vars/], - ':html' => [qw/:html2 :html3 :html4 :netscape/], - ':standard' => [qw/:html2 :html3 :html4 :form :cgi/], - ':push' => [qw/multipart_init multipart_start multipart_end multipart_final/], - ':all' => [qw/:html2 :html3 :netscape :form :cgi :internal :html4/] - ); - -# Custom 'can' method for both autoloaded and non-autoloaded subroutines. -# Author: Cees Hek <cees@sitesuite.com.au> - -sub can { - my($class, $method) = @_; - - # See if UNIVERSAL::can finds it. - - if (my $func = $class -> SUPER::can($method) ){ - return $func; - } - - # Try to compile the function. - - eval { - # _compile looks at $AUTOLOAD for the function name. - - local $AUTOLOAD = join "::", $class, $method; - &_compile; - }; - - # Now that the function is loaded (if it exists) - # just use UNIVERSAL::can again to do the work. - - return $class -> SUPER::can($method); -} - -# to import symbols into caller -sub import { - my $self = shift; - - # This causes modules to clash. - undef %EXPORT_OK; - undef %EXPORT; - - $self->_setup_symbols(@_); - my ($callpack, $callfile, $callline) = caller; - - # To allow overriding, search through the packages - # Till we find one in which the correct subroutine is defined. - my @packages = ($self,@{"$self\:\:ISA"}); - for $sym (keys %EXPORT) { - my $pck; - my $def = ${"$self\:\:AutoloadClass"} || $DefaultClass; - for $pck (@packages) { - if (defined(&{"$pck\:\:$sym"})) { - $def = $pck; - last; - } - } - *{"${callpack}::$sym"} = \&{"$def\:\:$sym"}; - } -} - -sub compile { - my $pack = shift; - $pack->_setup_symbols('-compile',@_); -} - -sub expand_tags { - my($tag) = @_; - return ("start_$1","end_$1") if $tag=~/^(?:\*|start_|end_)(.+)/; - my(@r); - return ($tag) unless $EXPORT_TAGS{$tag}; - for (@{$EXPORT_TAGS{$tag}}) { - push(@r,&expand_tags($_)); - } - return @r; -} - -#### Method: new -# The new routine. This will check the current environment -# for an existing query string, and initialize itself, if so. -#### -sub new { - my($class,@initializer) = @_; - my $self = {}; - - bless $self,ref $class || $class || $DefaultClass; - - # always use a tempfile - $self->{'use_tempfile'} = 1; - - if (ref($initializer[0]) - && (UNIVERSAL::isa($initializer[0],'Apache') - || - UNIVERSAL::isa($initializer[0],'Apache2::RequestRec') - )) { - $self->r(shift @initializer); - } - if (ref($initializer[0]) - && (UNIVERSAL::isa($initializer[0],'CODE'))) { - $self->upload_hook(shift @initializer, shift @initializer); - $self->{'use_tempfile'} = shift @initializer if (@initializer > 0); - } - if ($MOD_PERL) { - if ($MOD_PERL == 1) { - $self->r(Apache->request) unless $self->r; - my $r = $self->r; - $r->register_cleanup(\&CGI::_reset_globals); - $self->_setup_symbols(@SAVED_SYMBOLS) if @SAVED_SYMBOLS; - } - else { - # XXX: once we have the new API - # will do a real PerlOptions -SetupEnv check - $self->r(Apache2::RequestUtil->request) unless $self->r; - my $r = $self->r; - $r->subprocess_env unless exists $ENV{REQUEST_METHOD}; - $r->pool->cleanup_register(\&CGI::_reset_globals); - $self->_setup_symbols(@SAVED_SYMBOLS) if @SAVED_SYMBOLS; - } - undef $NPH; - } - $self->_reset_globals if $PERLEX; - $self->init(@initializer); - return $self; -} - -# We provide a DESTROY method so that we can ensure that -# temporary files are closed (via Fh->DESTROY) before they -# are unlinked (via CGITempFile->DESTROY) because it is not -# possible to unlink an open file on Win32. We explicitly -# call DESTROY on each, rather than just undefing them and -# letting Perl DESTROY them by garbage collection, in case the -# user is still holding any reference to them as well. -sub DESTROY { - my $self = shift; - if ($OS eq 'WINDOWS') { - for my $href (values %{$self->{'.tmpfiles'}}) { - $href->{hndl}->DESTROY if defined $href->{hndl}; - $href->{name}->DESTROY if defined $href->{name}; - } - } -} - -sub r { - my $self = shift; - my $r = $self->{'.r'}; - $self->{'.r'} = shift if @_; - $r; -} - -sub upload_hook { - my $self; - if (ref $_[0] eq 'CODE') { - $CGI::Q = $self = $CGI::DefaultClass->new(@_); - } else { - $self = shift; - } - my ($hook,$data,$use_tempfile) = @_; - $self->{'.upload_hook'} = $hook; - $self->{'.upload_data'} = $data; - $self->{'use_tempfile'} = $use_tempfile if defined $use_tempfile; -} - -#### Method: param -# Returns the value(s)of a named parameter. -# If invoked in a list context, returns the -# entire list. Otherwise returns the first -# member of the list. -# If name is not provided, return a list of all -# the known parameters names available. -# If more than one argument is provided, the -# second and subsequent arguments are used to -# set the value of the parameter. -#### -sub param { - my($self,@p) = self_or_default(@_); - return $self->all_parameters unless @p; - my($name,$value,@other); - - # For compatibility between old calling style and use_named_parameters() style, - # we have to special case for a single parameter present. - if (@p > 1) { - ($name,$value,@other) = rearrange([NAME,[DEFAULT,VALUE,VALUES]],@p); - my(@values); - - if (substr($p[0],0,1) eq '-') { - @values = defined($value) ? (ref($value) && ref($value) eq 'ARRAY' ? @{$value} : $value) : (); - } else { - for ($value,@other) { - push(@values,$_) if defined($_); - } - } - # If values is provided, then we set it. - if (@values or defined $value) { - $self->add_parameter($name); - $self->{param}{$name}=[@values]; - } - } else { - $name = $p[0]; - } - - return unless defined($name) && $self->{param}{$name}; - - my @result = @{$self->{param}{$name}}; - - if ($PARAM_UTF8) { - eval "require Encode; 1;" unless Encode->can('decode'); # bring in these functions - @result = map {ref $_ ? $_ : Encode::decode(utf8=>$_) } @result; - } - - return wantarray ? @result : $result[0]; -} - -sub self_or_default { - return @_ if defined($_[0]) && (!ref($_[0])) &&($_[0] eq 'CGI'); - unless (defined($_[0]) && - (ref($_[0]) eq 'CGI' || UNIVERSAL::isa($_[0],'CGI')) # slightly optimized for common case - ) { - $Q = $CGI::DefaultClass->new unless defined($Q); - unshift(@_,$Q); - } - return wantarray ? @_ : $Q; -} - -sub self_or_CGI { - local $^W=0; # prevent a warning - if (defined($_[0]) && - (substr(ref($_[0]),0,3) eq 'CGI' - || UNIVERSAL::isa($_[0],'CGI'))) { - return @_; - } else { - return ($DefaultClass,@_); - } -} - -######################################## -# THESE METHODS ARE MORE OR LESS PRIVATE -# GO TO THE __DATA__ SECTION TO SEE MORE -# PUBLIC METHODS -######################################## - -# Initialize the query object from the environment. -# If a parameter list is found, this object will be set -# to a hash in which parameter names are keys -# and the values are stored as lists -# If a keyword list is found, this method creates a bogus -# parameter list with the single parameter 'keywords'. - -sub init { - my $self = shift; - my($query_string,$meth,$content_length,$fh,@lines) = ('','','',''); - - my $is_xforms; - - my $initializer = shift; # for backward compatibility - local($/) = "\n"; - - # set autoescaping on by default - $self->{'escape'} = 1; - - # if we get called more than once, we want to initialize - # ourselves from the original query (which may be gone - # if it was read from STDIN originally.) - if (defined(@QUERY_PARAM) && !defined($initializer)) { - for my $name (@QUERY_PARAM) { - my $val = $QUERY_PARAM{$name}; # always an arrayref; - $self->param('-name'=>$name,'-value'=> $val); - if (defined $val and ref $val eq 'ARRAY') { - for my $fh (grep {defined(fileno($_))} @$val) { - seek($fh,0,0); # reset the filehandle. - } - - } - } - $self->charset($QUERY_CHARSET); - $self->{'.fieldnames'} = {%QUERY_FIELDNAMES}; - $self->{'.tmpfiles'} = {%QUERY_TMPFILES}; - return; - } - - $meth=$ENV{'REQUEST_METHOD'} if defined($ENV{'REQUEST_METHOD'}); - $content_length = defined($ENV{'CONTENT_LENGTH'}) ? $ENV{'CONTENT_LENGTH'} : 0; - - $fh = to_filehandle($initializer) if $initializer; - - # set charset to the safe ISO-8859-1 - $self->charset('ISO-8859-1'); - - METHOD: { - - # avoid unreasonably large postings - if (($POST_MAX > 0) && ($content_length > $POST_MAX)) { - #discard the post, unread - $self->cgi_error("413 Request entity too large"); - last METHOD; - } - - # Process multipart postings, but only if the initializer is - # not defined. - if ($meth eq 'POST' - && defined($ENV{'CONTENT_TYPE'}) - && $ENV{'CONTENT_TYPE'}=~m|^multipart/form-data| - && !defined($initializer) - ) { - my($boundary) = $ENV{'CONTENT_TYPE'} =~ /boundary=\"?([^\";,]+)\"?/; - $self->read_multipart($boundary,$content_length); - last METHOD; - } - - # Process XForms postings. We know that we have XForms in the - # following cases: - # method eq 'POST' && content-type eq 'application/xml' - # method eq 'POST' && content-type =~ /multipart\/related.+start=/ - # There are more cases, actually, but for now, we don't support other - # methods for XForm posts. - # In a XForm POST, the QUERY_STRING is parsed normally. - # If the content-type is 'application/xml', we just set the param - # XForms:Model (referring to the xml syntax) param containing the - # unparsed XML data. - # In the case of multipart/related we set XForms:Model as above, but - # the other parts are available as uploads with the Content-ID as the - # the key. - # See the URL below for XForms specs on this issue. - # http://www.w3.org/TR/2006/REC-xforms-20060314/slice11.html#submit-options - if ($meth eq 'POST' && defined($ENV{'CONTENT_TYPE'})) { - if ($ENV{'CONTENT_TYPE'} eq 'application/xml') { - my($param) = 'XForms:Model'; - my($value) = ''; - $self->add_parameter($param); - $self->read_from_client(\$value,$content_length,0) - if $content_length > 0; - push (@{$self->{param}{$param}},$value); - $is_xforms = 1; - } elsif ($ENV{'CONTENT_TYPE'} =~ /multipart\/related.+boundary=\"?([^\";,]+)\"?.+start=\"?\<?([^\"\>]+)\>?\"?/) { - my($boundary,$start) = ($1,$2); - my($param) = 'XForms:Model'; - $self->add_parameter($param); - my($value) = $self->read_multipart_related($start,$boundary,$content_length,0); - push (@{$self->{param}{$param}},$value); - if ($MOD_PERL) { - $query_string = $self->r->args; - } else { - $query_string = $ENV{'QUERY_STRING'} if defined $ENV{'QUERY_STRING'}; - $query_string ||= $ENV{'REDIRECT_QUERY_STRING'} if defined $ENV{'REDIRECT_QUERY_STRING'}; - } - $is_xforms = 1; - } - } - - - # If initializer is defined, then read parameters - # from it. - if (!$is_xforms && defined($initializer)) { - if (UNIVERSAL::isa($initializer,'CGI')) { - $query_string = $initializer->query_string; - last METHOD; - } - if (ref($initializer) && ref($initializer) eq 'HASH') { - for (keys %$initializer) { - $self->param('-name'=>$_,'-value'=>$initializer->{$_}); - } - last METHOD; - } - - if (defined($fh) && ($fh ne '')) { - while (<$fh>) { - chomp; - last if /^=/; - push(@lines,$_); - } - # massage back into standard format - if ("@lines" =~ /=/) { - $query_string=join("&",@lines); - } else { - $query_string=join("+",@lines); - } - last METHOD; - } - - # last chance -- treat it as a string - $initializer = $$initializer if ref($initializer) eq 'SCALAR'; - $query_string = $initializer; - - last METHOD; - } - - # If method is GET or HEAD, fetch the query from - # the environment. - if ($is_xforms || $meth=~/^(GET|HEAD)$/) { - if ($MOD_PERL) { - $query_string = $self->r->args; - } else { - $query_string = $ENV{'QUERY_STRING'} if defined $ENV{'QUERY_STRING'}; - $query_string ||= $ENV{'REDIRECT_QUERY_STRING'} if defined $ENV{'REDIRECT_QUERY_STRING'}; - } - last METHOD; - } - - if ($meth eq 'POST' || $meth eq 'PUT') { - if ( $content_length > 0 ) { - $self->read_from_client(\$query_string,$content_length,0); - } - else { - $self->read_from_stdin(\$query_string); - # should this be PUTDATA in case of PUT ? - my($param) = $meth . 'DATA' ; - $self->add_parameter($param) ; - push (@{$self->{param}{$param}},$query_string); - undef $query_string ; - } - # Some people want to have their cake and eat it too! - # Uncomment this line to have the contents of the query string - # APPENDED to the POST data. - # $query_string .= (length($query_string) ? '&' : '') . $ENV{'QUERY_STRING'} if defined $ENV{'QUERY_STRING'}; - last METHOD; - } - - # If $meth is not of GET, POST, PUT or HEAD, assume we're - # being debugged offline. - # Check the command line and then the standard input for data. - # We use the shellwords package in order to behave the way that - # UN*X programmers expect. - if ($DEBUG) - { - my $cmdline_ret = read_from_cmdline(); - $query_string = $cmdline_ret->{'query_string'}; - if (defined($cmdline_ret->{'subpath'})) - { - $self->path_info($cmdline_ret->{'subpath'}); - } - } - } - -# YL: Begin Change for XML handler 10/19/2001 - if (!$is_xforms && ($meth eq 'POST' || $meth eq 'PUT') - && defined($ENV{'CONTENT_TYPE'}) - && $ENV{'CONTENT_TYPE'} !~ m|^application/x-www-form-urlencoded| - && $ENV{'CONTENT_TYPE'} !~ m|^multipart/form-data| ) { - my($param) = $meth . 'DATA' ; - $self->add_parameter($param) ; - push (@{$self->{param}{$param}},$query_string); - undef $query_string ; - } -# YL: End Change for XML handler 10/19/2001 - - # We now have the query string in hand. We do slightly - # different things for keyword lists and parameter lists. - if (defined $query_string && length $query_string) { - if ($query_string =~ /[&=;]/) { - $self->parse_params($query_string); - } else { - $self->add_parameter('keywords'); - $self->{param}{'keywords'} = [$self->parse_keywordlist($query_string)]; - } - } - - # Special case. Erase everything if there is a field named - # .defaults. - if ($self->param('.defaults')) { - $self->delete_all(); - } - - # hash containing our defined fieldnames - $self->{'.fieldnames'} = {}; - for ($self->param('.cgifields')) { - $self->{'.fieldnames'}->{$_}++; - } - - # Clear out our default submission button flag if present - $self->delete('.submit'); - $self->delete('.cgifields'); - - $self->save_request unless defined $initializer; -} - -# FUNCTIONS TO OVERRIDE: -# Turn a string into a filehandle -sub to_filehandle { - my $thingy = shift; - return undef unless $thingy; - return $thingy if UNIVERSAL::isa($thingy,'GLOB'); - return $thingy if UNIVERSAL::isa($thingy,'FileHandle'); - if (!ref($thingy)) { - my $caller = 1; - while (my $package = caller($caller++)) { - my($tmp) = $thingy=~/[\':]/ ? $thingy : "$package\:\:$thingy"; - return $tmp if defined(fileno($tmp)); - } - } - return undef; -} - -# send output to the browser -sub put { - my($self,@p) = self_or_default(@_); - $self->print(@p); -} - -# print to standard output (for overriding in mod_perl) -sub print { - shift; - CORE::print(@_); -} - -# get/set last cgi_error -sub cgi_error { - my ($self,$err) = self_or_default(@_); - $self->{'.cgi_error'} = $err if defined $err; - return $self->{'.cgi_error'}; -} - -sub save_request { - my($self) = @_; - # We're going to play with the package globals now so that if we get called - # again, we initialize ourselves in exactly the same way. This allows - # us to have several of these objects. - @QUERY_PARAM = $self->param; # save list of parameters - for (@QUERY_PARAM) { - next unless defined $_; - $QUERY_PARAM{$_}=$self->{param}{$_}; - } - $QUERY_CHARSET = $self->charset; - %QUERY_FIELDNAMES = %{$self->{'.fieldnames'}}; - %QUERY_TMPFILES = %{ $self->{'.tmpfiles'} || {} }; -} - -sub parse_params { - my($self,$tosplit) = @_; - my(@pairs) = split(/[&;]/,$tosplit); - my($param,$value); - for (@pairs) { - ($param,$value) = split('=',$_,2); - next unless defined $param; - next if $NO_UNDEF_PARAMS and not defined $value; - $value = '' unless defined $value; - $param = unescape($param); - $value = unescape($value); - $self->add_parameter($param); - push (@{$self->{param}{$param}},$value); - } -} - -sub add_parameter { - my($self,$param)=@_; - return unless defined $param; - push (@{$self->{'.parameters'}},$param) - unless defined($self->{param}{$param}); -} - -sub all_parameters { - my $self = shift; - return () unless defined($self) && $self->{'.parameters'}; - return () unless @{$self->{'.parameters'}}; - return @{$self->{'.parameters'}}; -} - -# put a filehandle into binary mode (DOS) -sub binmode { - return unless defined($_[1]) && defined fileno($_[1]); - CORE::binmode($_[1]); -} - -sub _make_tag_func { - my ($self,$tagname) = @_; - my $func = qq( - sub $tagname { - my (\$q,\$a,\@rest) = self_or_default(\@_); - my(\$attr) = ''; - if (ref(\$a) && ref(\$a) eq 'HASH') { - my(\@attr) = make_attributes(\$a,\$q->{'escape'}); - \$attr = " \@attr" if \@attr; - } else { - unshift \@rest,\$a if defined \$a; - } - ); - if ($tagname=~/start_(\w+)/i) { - $func .= qq! return "<\L$1\E\$attr>";} !; - } elsif ($tagname=~/end_(\w+)/i) { - $func .= qq! return "<\L/$1\E>"; } !; - } else { - $func .= qq# - return \$XHTML ? "\L<$tagname\E\$attr />" : "\L<$tagname\E\$attr>" unless \@rest; - my(\$tag,\$untag) = ("\L<$tagname\E\$attr>","\L</$tagname>\E"); - my \@result = map { "\$tag\$_\$untag" } - (ref(\$rest[0]) eq 'ARRAY') ? \@{\$rest[0]} : "\@rest"; - return "\@result"; - }#; - } -return $func; -} - -sub AUTOLOAD { - print STDERR "CGI::AUTOLOAD for $AUTOLOAD\n" if $CGI::AUTOLOAD_DEBUG; - my $func = &_compile; - goto &$func; -} - -sub _compile { - my($func) = $AUTOLOAD; - my($pack,$func_name); - { - local($1,$2); # this fixes an obscure variable suicide problem. - $func=~/(.+)::([^:]+)$/; - ($pack,$func_name) = ($1,$2); - $pack=~s/::SUPER$//; # fix another obscure problem - $pack = ${"$pack\:\:AutoloadClass"} || $CGI::DefaultClass - unless defined(${"$pack\:\:AUTOLOADED_ROUTINES"}); - - my($sub) = \%{"$pack\:\:SUBS"}; - unless (%$sub) { - my($auto) = \${"$pack\:\:AUTOLOADED_ROUTINES"}; - local ($@,$!); - eval "package $pack; $$auto"; - croak("$AUTOLOAD: $@") if $@; - $$auto = ''; # Free the unneeded storage (but don't undef it!!!) - } - my($code) = $sub->{$func_name}; - - $code = "sub $AUTOLOAD { }" if (!$code and $func_name eq 'DESTROY'); - if (!$code) { - (my $base = $func_name) =~ s/^(start_|end_)//i; - if ($EXPORT{':any'} || - $EXPORT{'-any'} || - $EXPORT{$base} || - (%EXPORT_OK || grep(++$EXPORT_OK{$_},&expand_tags(':html'))) - && $EXPORT_OK{$base}) { - $code = $CGI::DefaultClass->_make_tag_func($func_name); - } - } - croak("Undefined subroutine $AUTOLOAD\n") unless $code; - local ($@,$!); - eval "package $pack; $code"; - if ($@) { - $@ =~ s/ at .*\n//; - croak("$AUTOLOAD: $@"); - } - } - CORE::delete($sub->{$func_name}); #free storage - return "$pack\:\:$func_name"; -} - -sub _selected { - my $self = shift; - my $value = shift; - return '' unless $value; - return $XHTML ? qq(selected="selected" ) : qq(selected ); -} - -sub _checked { - my $self = shift; - my $value = shift; - return '' unless $value; - return $XHTML ? qq(checked="checked" ) : qq(checked ); -} - -sub _reset_globals { initialize_globals(); } - -sub _setup_symbols { - my $self = shift; - my $compile = 0; - - # to avoid reexporting unwanted variables - undef %EXPORT; - - for (@_) { - $HEADERS_ONCE++, next if /^[:-]unique_headers$/; - $NPH++, next if /^[:-]nph$/; - $NOSTICKY++, next if /^[:-]nosticky$/; - $DEBUG=0, next if /^[:-]no_?[Dd]ebug$/; - $DEBUG=2, next if /^[:-][Dd]ebug$/; - $USE_PARAM_SEMICOLONS++, next if /^[:-]newstyle_urls$/; - $PARAM_UTF8++, next if /^[:-]utf8$/; - $XHTML++, next if /^[:-]xhtml$/; - $XHTML=0, next if /^[:-]no_?xhtml$/; - $USE_PARAM_SEMICOLONS=0, next if /^[:-]oldstyle_urls$/; - $PRIVATE_TEMPFILES++, next if /^[:-]private_tempfiles$/; - $TABINDEX++, next if /^[:-]tabindex$/; - $CLOSE_UPLOAD_FILES++, next if /^[:-]close_upload_files$/; - $EXPORT{$_}++, next if /^[:-]any$/; - $compile++, next if /^[:-]compile$/; - $NO_UNDEF_PARAMS++, next if /^[:-]no_undef_params$/; - - # This is probably extremely evil code -- to be deleted some day. - if (/^[-]autoload$/) { - my($pkg) = caller(1); - *{"${pkg}::AUTOLOAD"} = sub { - my($routine) = $AUTOLOAD; - $routine =~ s/^.*::/CGI::/; - &$routine; - }; - next; - } - - for (&expand_tags($_)) { - tr/a-zA-Z0-9_//cd; # don't allow weird function names - $EXPORT{$_}++; - } - } - _compile_all(keys %EXPORT) if $compile; - @SAVED_SYMBOLS = @_; -} - -sub charset { - my ($self,$charset) = self_or_default(@_); - $self->{'.charset'} = $charset if defined $charset; - $self->{'.charset'}; -} - -sub element_id { - my ($self,$new_value) = self_or_default(@_); - $self->{'.elid'} = $new_value if defined $new_value; - sprintf('%010d',$self->{'.elid'}++); -} - -sub element_tab { - my ($self,$new_value) = self_or_default(@_); - $self->{'.etab'} ||= 1; - $self->{'.etab'} = $new_value if defined $new_value; - my $tab = $self->{'.etab'}++; - return '' unless $TABINDEX or defined $new_value; - return qq(tabindex="$tab" ); -} - -############################################################################### -################# THESE FUNCTIONS ARE AUTOLOADED ON DEMAND #################### -############################################################################### -$AUTOLOADED_ROUTINES = ''; # get rid of -w warning -$AUTOLOADED_ROUTINES=<<'END_OF_AUTOLOAD'; - -%SUBS = ( - -'URL_ENCODED'=> <<'END_OF_FUNC', -sub URL_ENCODED { 'application/x-www-form-urlencoded'; } -END_OF_FUNC - -'MULTIPART' => <<'END_OF_FUNC', -sub MULTIPART { 'multipart/form-data'; } -END_OF_FUNC - -'SERVER_PUSH' => <<'END_OF_FUNC', -sub SERVER_PUSH { 'multipart/x-mixed-replace;boundary="' . shift() . '"'; } -END_OF_FUNC - -'new_MultipartBuffer' => <<'END_OF_FUNC', -# Create a new multipart buffer -sub new_MultipartBuffer { - my($self,$boundary,$length) = @_; - return MultipartBuffer->new($self,$boundary,$length); -} -END_OF_FUNC - -'read_from_client' => <<'END_OF_FUNC', -# Read data from a file handle -sub read_from_client { - my($self, $buff, $len, $offset) = @_; - local $^W=0; # prevent a warning - return $MOD_PERL - ? $self->r->read($$buff, $len, $offset) - : read(\*STDIN, $$buff, $len, $offset); -} -END_OF_FUNC - -'read_from_stdin' => <<'END_OF_FUNC', -# Read data from stdin until all is read -sub read_from_stdin { - my($self, $buff) = @_; - local $^W=0; # prevent a warning - - # - # TODO: loop over STDIN until all is read - # - - my($eoffound) = 0; - my($localbuf) = ''; - my($tempbuf) = ''; - my($bufsiz) = 1024; - my($res); - while ($eoffound == 0) { - if ( $MOD_PERL ) { - $res = $self->r->read($tempbuf, $bufsiz, 0) - } - else { - $res = read(\*STDIN, $tempbuf, $bufsiz); - } - - if ( !defined($res) ) { - # TODO: how to do error reporting ? - $eoffound = 1; - last; - } - if ( $res == 0 ) { - $eoffound = 1; - last; - } - $localbuf .= $tempbuf; - } - - $$buff = $localbuf; - - return $res; -} -END_OF_FUNC - -'delete' => <<'END_OF_FUNC', -#### Method: delete -# Deletes the named parameter entirely. -#### -sub delete { - my($self,@p) = self_or_default(@_); - my(@names) = rearrange([NAME],@p); - my @to_delete = ref($names[0]) eq 'ARRAY' ? @$names[0] : @names; - my %to_delete; - for my $name (@to_delete) - { - CORE::delete $self->{param}{$name}; - CORE::delete $self->{'.fieldnames'}->{$name}; - $to_delete{$name}++; - } - @{$self->{'.parameters'}}=grep { !exists($to_delete{$_}) } $self->param(); - return; -} -END_OF_FUNC - -#### Method: import_names -# Import all parameters into the given namespace. -# Assumes namespace 'Q' if not specified -#### -'import_names' => <<'END_OF_FUNC', -sub import_names { - my($self,$namespace,$delete) = self_or_default(@_); - $namespace = 'Q' unless defined($namespace); - die "Can't import names into \"main\"\n" if \%{"${namespace}::"} == \%::; - if ($delete || $MOD_PERL || exists $ENV{'FCGI_ROLE'}) { - # can anyone find an easier way to do this? - for (keys %{"${namespace}::"}) { - local *symbol = "${namespace}::${_}"; - undef $symbol; - undef @symbol; - undef %symbol; - } - } - my($param,@value,$var); - for $param ($self->param) { - # protect against silly names - ($var = $param)=~tr/a-zA-Z0-9_/_/c; - $var =~ s/^(?=\d)/_/; - local *symbol = "${namespace}::$var"; - @value = $self->param($param); - @symbol = @value; - $symbol = $value[0]; - } -} -END_OF_FUNC - -#### Method: keywords -# Keywords acts a bit differently. Calling it in a list context -# returns the list of keywords. -# Calling it in a scalar context gives you the size of the list. -#### -'keywords' => <<'END_OF_FUNC', -sub keywords { - my($self,@values) = self_or_default(@_); - # If values is provided, then we set it. - $self->{param}{'keywords'}=[@values] if @values; - my(@result) = defined($self->{param}{'keywords'}) ? @{$self->{param}{'keywords'}} : (); - @result; -} -END_OF_FUNC - -# These are some tie() interfaces for compatibility -# with Steve Brenner's cgi-lib.pl routines -'Vars' => <<'END_OF_FUNC', -sub Vars { - my $q = shift; - my %in; - tie(%in,CGI,$q); - return %in if wantarray; - return \%in; -} -END_OF_FUNC - -# These are some tie() interfaces for compatibility -# with Steve Brenner's cgi-lib.pl routines -'ReadParse' => <<'END_OF_FUNC', -sub ReadParse { - local(*in); - if (@_) { - *in = $_[0]; - } else { - my $pkg = caller(); - *in=*{"${pkg}::in"}; - } - tie(%in,CGI); - return scalar(keys %in); -} -END_OF_FUNC - -'PrintHeader' => <<'END_OF_FUNC', -sub PrintHeader { - my($self) = self_or_default(@_); - return $self->header(); -} -END_OF_FUNC - -'HtmlTop' => <<'END_OF_FUNC', -sub HtmlTop { - my($self,@p) = self_or_default(@_); - return $self->start_html(@p); -} -END_OF_FUNC - -'HtmlBot' => <<'END_OF_FUNC', -sub HtmlBot { - my($self,@p) = self_or_default(@_); - return $self->end_html(@p); -} -END_OF_FUNC - -'SplitParam' => <<'END_OF_FUNC', -sub SplitParam { - my ($param) = @_; - my (@params) = split ("\0", $param); - return (wantarray ? @params : $params[0]); -} -END_OF_FUNC - -'MethGet' => <<'END_OF_FUNC', -sub MethGet { - return request_method() eq 'GET'; -} -END_OF_FUNC - -'MethPost' => <<'END_OF_FUNC', -sub MethPost { - return request_method() eq 'POST'; -} -END_OF_FUNC - -'MethPut' => <<'END_OF_FUNC', -sub MethPut { - return request_method() eq 'PUT'; -} -END_OF_FUNC - -'TIEHASH' => <<'END_OF_FUNC', -sub TIEHASH { - my $class = shift; - my $arg = $_[0]; - if (ref($arg) && UNIVERSAL::isa($arg,'CGI')) { - return $arg; - } - return $Q ||= $class->new(@_); -} -END_OF_FUNC - -'STORE' => <<'END_OF_FUNC', -sub STORE { - my $self = shift; - my $tag = shift; - my $vals = shift; - my @vals = index($vals,"\0")!=-1 ? split("\0",$vals) : $vals; - $self->param(-name=>$tag,-value=>\@vals); -} -END_OF_FUNC - -'FETCH' => <<'END_OF_FUNC', -sub FETCH { - return $_[0] if $_[1] eq 'CGI'; - return undef unless defined $_[0]->param($_[1]); - return join("\0",$_[0]->param($_[1])); -} -END_OF_FUNC - -'FIRSTKEY' => <<'END_OF_FUNC', -sub FIRSTKEY { - $_[0]->{'.iterator'}=0; - $_[0]->{'.parameters'}->[$_[0]->{'.iterator'}++]; -} -END_OF_FUNC - -'NEXTKEY' => <<'END_OF_FUNC', -sub NEXTKEY { - $_[0]->{'.parameters'}->[$_[0]->{'.iterator'}++]; -} -END_OF_FUNC - -'EXISTS' => <<'END_OF_FUNC', -sub EXISTS { - exists $_[0]->{param}{$_[1]}; -} -END_OF_FUNC - -'DELETE' => <<'END_OF_FUNC', -sub DELETE { - $_[0]->delete($_[1]); -} -END_OF_FUNC - -'CLEAR' => <<'END_OF_FUNC', -sub CLEAR { - %{$_[0]}=(); -} -#### -END_OF_FUNC - -#### -# Append a new value to an existing query -#### -'append' => <<'EOF', -sub append { - my($self,@p) = self_or_default(@_); - my($name,$value) = rearrange([NAME,[VALUE,VALUES]],@p); - my(@values) = defined($value) ? (ref($value) ? @{$value} : $value) : (); - if (@values) { - $self->add_parameter($name); - push(@{$self->{param}{$name}},@values); - } - return $self->param($name); -} -EOF - -#### Method: delete_all -# Delete all parameters -#### -'delete_all' => <<'EOF', -sub delete_all { - my($self) = self_or_default(@_); - my @param = $self->param(); - $self->delete(@param); -} -EOF - -'Delete' => <<'EOF', -sub Delete { - my($self,@p) = self_or_default(@_); - $self->delete(@p); -} -EOF - -'Delete_all' => <<'EOF', -sub Delete_all { - my($self,@p) = self_or_default(@_); - $self->delete_all(@p); -} -EOF - -#### Method: autoescape -# If you want to turn off the autoescaping features, -# call this method with undef as the argument -'autoEscape' => <<'END_OF_FUNC', -sub autoEscape { - my($self,$escape) = self_or_default(@_); - my $d = $self->{'escape'}; - $self->{'escape'} = $escape; - $d; -} -END_OF_FUNC - - -#### Method: version -# Return the current version -#### -'version' => <<'END_OF_FUNC', -sub version { - return $VERSION; -} -END_OF_FUNC - -#### Method: url_param -# Return a parameter in the QUERY_STRING, regardless of -# whether this was a POST or a GET -#### -'url_param' => <<'END_OF_FUNC', -sub url_param { - my ($self,@p) = self_or_default(@_); - my $name = shift(@p); - return undef unless exists($ENV{QUERY_STRING}); - unless (exists($self->{'.url_param'})) { - $self->{'.url_param'}={}; # empty hash - if ($ENV{QUERY_STRING} =~ /=/) { - my(@pairs) = split(/[&;]/,$ENV{QUERY_STRING}); - my($param,$value); - for (@pairs) { - ($param,$value) = split('=',$_,2); - $param = unescape($param); - $value = unescape($value); - push(@{$self->{'.url_param'}->{$param}},$value); - } - } else { - $self->{'.url_param'}->{'keywords'} = [$self->parse_keywordlist($ENV{QUERY_STRING})]; - } - } - return keys %{$self->{'.url_param'}} unless defined($name); - return () unless $self->{'.url_param'}->{$name}; - return wantarray ? @{$self->{'.url_param'}->{$name}} - : $self->{'.url_param'}->{$name}->[0]; -} -END_OF_FUNC - -#### Method: Dump -# Returns a string in which all the known parameter/value -# pairs are represented as nested lists, mainly for the purposes -# of debugging. -#### -'Dump' => <<'END_OF_FUNC', -sub Dump { - my($self) = self_or_default(@_); - my($param,$value,@result); - return '<ul></ul>' unless $self->param; - push(@result,"<ul>"); - for $param ($self->param) { - my($name)=$self->escapeHTML($param); - push(@result,"<li><strong>$name</strong></li>"); - push(@result,"<ul>"); - for $value ($self->param($param)) { - $value = $self->escapeHTML($value); - $value =~ s/\n/<br \/>\n/g; - push(@result,"<li>$value</li>"); - } - push(@result,"</ul>"); - } - push(@result,"</ul>"); - return join("\n",@result); -} -END_OF_FUNC - -#### Method as_string -# -# synonym for "dump" -#### -'as_string' => <<'END_OF_FUNC', -sub as_string { - &Dump(@_); -} -END_OF_FUNC - -#### Method: save -# Write values out to a filehandle in such a way that they can -# be reinitialized by the filehandle form of the new() method -#### -'save' => <<'END_OF_FUNC', -sub save { - my($self,$filehandle) = self_or_default(@_); - $filehandle = to_filehandle($filehandle); - my($param); - local($,) = ''; # set print field separator back to a sane value - local($\) = ''; # set output line separator to a sane value - for $param ($self->param) { - my($escaped_param) = escape($param); - my($value); - for $value ($self->param($param)) { - print $filehandle "$escaped_param=",escape("$value"),"\n"; - } - } - for (keys %{$self->{'.fieldnames'}}) { - print $filehandle ".cgifields=",escape("$_"),"\n"; - } - print $filehandle "=\n"; # end of record -} -END_OF_FUNC - - -#### Method: save_parameters -# An alias for save() that is a better name for exportation. -# Only intended to be used with the function (non-OO) interface. -#### -'save_parameters' => <<'END_OF_FUNC', -sub save_parameters { - my $fh = shift; - return save(to_filehandle($fh)); -} -END_OF_FUNC - -#### Method: restore_parameters -# A way to restore CGI parameters from an initializer. -# Only intended to be used with the function (non-OO) interface. -#### -'restore_parameters' => <<'END_OF_FUNC', -sub restore_parameters { - $Q = $CGI::DefaultClass->new(@_); -} -END_OF_FUNC - -#### Method: multipart_init -# Return a Content-Type: style header for server-push -# This has to be NPH on most web servers, and it is advisable to set $| = 1 -# -# Many thanks to Ed Jordan <ed@fidalgo.net> for this -# contribution, updated by Andrew Benham (adsb@bigfoot.com) -#### -'multipart_init' => <<'END_OF_FUNC', -sub multipart_init { - my($self,@p) = self_or_default(@_); - my($boundary,@other) = rearrange_header([BOUNDARY],@p); - $boundary = $boundary || '------- =_aaaaaaaaaa0'; - $self->{'separator'} = "$CRLF--$boundary$CRLF"; - $self->{'final_separator'} = "$CRLF--$boundary--$CRLF"; - $type = SERVER_PUSH($boundary); - return $self->header( - -nph => 0, - -type => $type, - (map { split "=", $_, 2 } @other), - ) . "WARNING: YOUR BROWSER DOESN'T SUPPORT THIS SERVER-PUSH TECHNOLOGY." . $self->multipart_end; -} -END_OF_FUNC - - -#### Method: multipart_start -# Return a Content-Type: style header for server-push, start of section -# -# Many thanks to Ed Jordan <ed@fidalgo.net> for this -# contribution, updated by Andrew Benham (adsb@bigfoot.com) -#### -'multipart_start' => <<'END_OF_FUNC', -sub multipart_start { - my(@header); - my($self,@p) = self_or_default(@_); - my($type,@other) = rearrange([TYPE],@p); - $type = $type || 'text/html'; - push(@header,"Content-Type: $type"); - - # rearrange() was designed for the HTML portion, so we - # need to fix it up a little. - for (@other) { - # Don't use \s because of perl bug 21951 - next unless my($header,$value) = /([^ \r\n\t=]+)=\"?(.+?)\"?$/; - ($_ = $header) =~ s/^(\w)(.*)/$1 . lc ($2) . ': '.$self->unescapeHTML($value)/e; - } - push(@header,@other); - my $header = join($CRLF,@header)."${CRLF}${CRLF}"; - return $header; -} -END_OF_FUNC - - -#### Method: multipart_end -# Return a MIME boundary separator for server-push, end of section -# -# Many thanks to Ed Jordan <ed@fidalgo.net> for this -# contribution -#### -'multipart_end' => <<'END_OF_FUNC', -sub multipart_end { - my($self,@p) = self_or_default(@_); - return $self->{'separator'}; -} -END_OF_FUNC - - -#### Method: multipart_final -# Return a MIME boundary separator for server-push, end of all sections -# -# Contributed by Andrew Benham (adsb@bigfoot.com) -#### -'multipart_final' => <<'END_OF_FUNC', -sub multipart_final { - my($self,@p) = self_or_default(@_); - return $self->{'final_separator'} . "WARNING: YOUR BROWSER DOESN'T SUPPORT THIS SERVER-PUSH TECHNOLOGY." . $CRLF; -} -END_OF_FUNC - - -#### Method: header -# Return a Content-Type: style header -# -#### -'header' => <<'END_OF_FUNC', -sub header { - my($self,@p) = self_or_default(@_); - my(@header); - - return "" if $self->{'.header_printed'}++ and $HEADERS_ONCE; - - my($type,$status,$cookie,$target,$expires,$nph,$charset,$attachment,$p3p,@other) = - rearrange([['TYPE','CONTENT_TYPE','CONTENT-TYPE'], - 'STATUS',['COOKIE','COOKIES'],'TARGET', - 'EXPIRES','NPH','CHARSET', - 'ATTACHMENT','P3P'],@p); - - $nph ||= $NPH; - - $type ||= 'text/html' unless defined($type); - - if (defined $charset) { - $self->charset($charset); - } else { - $charset = $self->charset if $type =~ /^text\//; - } - $charset ||= ''; - - # rearrange() was designed for the HTML portion, so we - # need to fix it up a little. - for (@other) { - # Don't use \s because of perl bug 21951 - next unless my($header,$value) = /([^ \r\n\t=]+)=\"?(.+?)\"?$/; - ($_ = $header) =~ s/^(\w)(.*)/"\u$1\L$2" . ': '.$self->unescapeHTML($value)/e; - } - - $type .= "; charset=$charset" - if $type ne '' - and $type !~ /\bcharset\b/ - and defined $charset - and $charset ne ''; - - # Maybe future compatibility. Maybe not. - my $protocol = $ENV{SERVER_PROTOCOL} || 'HTTP/1.0'; - push(@header,$protocol . ' ' . ($status || '200 OK')) if $nph; - push(@header,"Server: " . &server_software()) if $nph; - - push(@header,"Status: $status") if $status; - push(@header,"Window-Target: $target") if $target; - if ($p3p) { - $p3p = join ' ',@$p3p if ref($p3p) eq 'ARRAY'; - push(@header,qq(P3P: policyref="/w3c/p3p.xml", CP="$p3p")); - } - # push all the cookies -- there may be several - if ($cookie) { - my(@cookie) = ref($cookie) && ref($cookie) eq 'ARRAY' ? @{$cookie} : $cookie; - for (@cookie) { - my $cs = UNIVERSAL::isa($_,'CGI::Cookie') ? $_->as_string : $_; - push(@header,"Set-Cookie: $cs") if $cs ne ''; - } - } - # if the user indicates an expiration time, then we need - # both an Expires and a Date header (so that the browser is - # uses OUR clock) - push(@header,"Expires: " . expires($expires,'http')) - if $expires; - push(@header,"Date: " . expires(0,'http')) if $expires || $cookie || $nph; - push(@header,"Pragma: no-cache") if $self->cache(); - push(@header,"Content-Disposition: attachment; filename=\"$attachment\"") if $attachment; - push(@header,map {ucfirst $_} @other); - push(@header,"Content-Type: $type") if $type ne ''; - my $header = join($CRLF,@header)."${CRLF}${CRLF}"; - if (($MOD_PERL >= 1) && !$nph) { - $self->r->send_cgi_header($header); - return ''; - } - return $header; -} -END_OF_FUNC - - -#### Method: cache -# Control whether header() will produce the no-cache -# Pragma directive. -#### -'cache' => <<'END_OF_FUNC', -sub cache { - my($self,$new_value) = self_or_default(@_); - $new_value = '' unless $new_value; - if ($new_value ne '') { - $self->{'cache'} = $new_value; - } - return $self->{'cache'}; -} -END_OF_FUNC - - -#### Method: redirect -# Return a Location: style header -# -#### -'redirect' => <<'END_OF_FUNC', -sub redirect { - my($self,@p) = self_or_default(@_); - my($url,$target,$status,$cookie,$nph,@other) = - rearrange([[LOCATION,URI,URL],TARGET,STATUS,['COOKIE','COOKIES'],NPH],@p); - $status = '302 Found' unless defined $status; - $url ||= $self->self_url; - my(@o); - for (@other) { tr/\"//d; push(@o,split("=",$_,2)); } - unshift(@o, - '-Status' => $status, - '-Location'=> $url, - '-nph' => $nph); - unshift(@o,'-Target'=>$target) if $target; - unshift(@o,'-Type'=>''); - my @unescaped; - unshift(@unescaped,'-Cookie'=>$cookie) if $cookie; - return $self->header((map {$self->unescapeHTML($_)} @o),@unescaped); -} -END_OF_FUNC - - -#### Method: start_html -# Canned HTML header -# -# Parameters: -# $title -> (optional) The title for this HTML document (-title) -# $author -> (optional) e-mail address of the author (-author) -# $base -> (optional) if set to true, will enter the BASE address of this document -# for resolving relative references (-base) -# $xbase -> (optional) alternative base at some remote location (-xbase) -# $target -> (optional) target window to load all links into (-target) -# $script -> (option) Javascript code (-script) -# $no_script -> (option) Javascript <noscript> tag (-noscript) -# $meta -> (optional) Meta information tags -# $head -> (optional) any other elements you'd like to incorporate into the <head> tag -# (a scalar or array ref) -# $style -> (optional) reference to an external style sheet -# @other -> (optional) any other named parameters you'd like to incorporate into -# the <body> tag. -#### -'start_html' => <<'END_OF_FUNC', -sub start_html { - my($self,@p) = &self_or_default(@_); - my($title,$author,$base,$xbase,$script,$noscript, - $target,$meta,$head,$style,$dtd,$lang,$encoding,$declare_xml,@other) = - rearrange([TITLE,AUTHOR,BASE,XBASE,SCRIPT,NOSCRIPT,TARGET, - META,HEAD,STYLE,DTD,LANG,ENCODING,DECLARE_XML],@p); - - $self->element_id(0); - $self->element_tab(0); - - $encoding = lc($self->charset) unless defined $encoding; - - # Need to sort out the DTD before it's okay to call escapeHTML(). - my(@result,$xml_dtd); - if ($dtd) { - if (defined(ref($dtd)) and (ref($dtd) eq 'ARRAY')) { - $dtd = $DEFAULT_DTD unless $dtd->[0] =~ m|^-//|; - } else { - $dtd = $DEFAULT_DTD unless $dtd =~ m|^-//|; - } - } else { - $dtd = $XHTML ? XHTML_DTD : $DEFAULT_DTD; - } - - $xml_dtd++ if ref($dtd) eq 'ARRAY' && $dtd->[0] =~ /\bXHTML\b/i; - $xml_dtd++ if ref($dtd) eq '' && $dtd =~ /\bXHTML\b/i; - push @result,qq(<?xml version="1.0" encoding="$encoding"?>) if $xml_dtd && $declare_xml; - - if (ref($dtd) && ref($dtd) eq 'ARRAY') { - push(@result,qq(<!DOCTYPE html\n\tPUBLIC "$dtd->[0]"\n\t "$dtd->[1]">)); - $DTD_PUBLIC_IDENTIFIER = $dtd->[0]; - } else { - push(@result,qq(<!DOCTYPE html\n\tPUBLIC "$dtd">)); - $DTD_PUBLIC_IDENTIFIER = $dtd; - } - - # Now that we know whether we're using the HTML 3.2 DTD or not, it's okay to - # call escapeHTML(). Strangely enough, the title needs to be escaped as - # HTML while the author needs to be escaped as a URL. - $title = $self->escapeHTML($title || 'Untitled Document'); - $author = $self->escape($author); - - if ($DTD_PUBLIC_IDENTIFIER =~ /[^X]HTML (2\.0|3\.2)/i) { - $lang = "" unless defined $lang; - $XHTML = 0; - } - else { - $lang = 'en-US' unless defined $lang; - } - - my $lang_bits = $lang ne '' ? qq( lang="$lang" xml:lang="$lang") : ''; - my $meta_bits = qq(<meta http-equiv="Content-Type" content="text/html; charset=$encoding" />) - if $XHTML && $encoding && !$declare_xml; - - push(@result,$XHTML ? qq(<html xmlns="http://www.w3.org/1999/xhtml"$lang_bits>\n<head>\n<title>$title</title>) - : ($lang ? qq(<html lang="$lang">) : "<html>") - . "<head><title>$title</title>"); - if (defined $author) { - push(@result,$XHTML ? "<link rev=\"made\" href=\"mailto:$author\" />" - : "<link rev=\"made\" href=\"mailto:$author\">"); - } - - if ($base || $xbase || $target) { - my $href = $xbase || $self->url('-path'=>1); - my $t = $target ? qq/ target="$target"/ : ''; - push(@result,$XHTML ? qq(<base href="$href"$t />) : qq(<base href="$href"$t>)); - } - - if ($meta && ref($meta) && (ref($meta) eq 'HASH')) { - for (keys %$meta) { push(@result,$XHTML ? qq(<meta name="$_" content="$meta->{$_}" />) - : qq(<meta name="$_" content="$meta->{$_}">)); } - } - - my $meta_bits_set = 0; - if( $head ) { - if( ref $head ) { - push @result, @$head; - $meta_bits_set = 1 if grep { /http-equiv=["']Content-Type/i }@$head; - } - else { - push @result, $head; - $meta_bits_set = 1 if $head =~ /http-equiv=["']Content-Type/i; - } - } - - # handle the infrequently-used -style and -script parameters - push(@result,$self->_style($style)) if defined $style; - push(@result,$self->_script($script)) if defined $script; - push(@result,$meta_bits) if defined $meta_bits and !$meta_bits_set; - - # handle -noscript parameter - push(@result,<<END) if $noscript; -<noscript> -$noscript -</noscript> -END - ; - my($other) = @other ? " @other" : ''; - push(@result,"</head>\n<body$other>\n"); - return join("\n",@result); -} -END_OF_FUNC - -### Method: _style -# internal method for generating a CSS style section -#### -'_style' => <<'END_OF_FUNC', -sub _style { - my ($self,$style) = @_; - my (@result); - - my $type = 'text/css'; - my $rel = 'stylesheet'; - - - my $cdata_start = $XHTML ? "\n<!--/* <![CDATA[ */" : "\n<!-- "; - my $cdata_end = $XHTML ? "\n/* ]]> */-->\n" : " -->\n"; - - my @s = ref($style) eq 'ARRAY' ? @$style : $style; - my $other = ''; - - for my $s (@s) { - if (ref($s)) { - my($src,$code,$verbatim,$stype,$alternate,$foo,@other) = - rearrange([qw(SRC CODE VERBATIM TYPE ALTERNATE FOO)], - ('-foo'=>'bar', - ref($s) eq 'ARRAY' ? @$s : %$s)); - my $type = defined $stype ? $stype : 'text/css'; - my $rel = $alternate ? 'alternate stylesheet' : 'stylesheet'; - $other = "@other" if @other; - - if (ref($src) eq "ARRAY") # Check to see if the $src variable is an array reference - { # If it is, push a LINK tag for each one - for $src (@$src) - { - push(@result,$XHTML ? qq(<link rel="$rel" type="$type" href="$src" $other/>) - : qq(<link rel="$rel" type="$type" href="$src"$other>)) if $src; - } - } - else - { # Otherwise, push the single -src, if it exists. - push(@result,$XHTML ? qq(<link rel="$rel" type="$type" href="$src" $other/>) - : qq(<link rel="$rel" type="$type" href="$src"$other>) - ) if $src; - } - if ($verbatim) { - my @v = ref($verbatim) eq 'ARRAY' ? @$verbatim : $verbatim; - push(@result, "<style type=\"text/css\">\n$_\n</style>") for @v; - } - my @c = ref($code) eq 'ARRAY' ? @$code : $code if $code; - push(@result,style({'type'=>$type},"$cdata_start\n$_\n$cdata_end")) for @c; - - } else { - my $src = $s; - push(@result,$XHTML ? qq(<link rel="$rel" type="$type" href="$src" $other/>) - : qq(<link rel="$rel" type="$type" href="$src"$other>)); - } - } - @result; -} -END_OF_FUNC - -'_script' => <<'END_OF_FUNC', -sub _script { - my ($self,$script) = @_; - my (@result); - - my (@scripts) = ref($script) eq 'ARRAY' ? @$script : ($script); - for $script (@scripts) { - my($src,$code,$language); - if (ref($script)) { # script is a hash - ($src,$code,$type) = - rearrange(['SRC','CODE',['LANGUAGE','TYPE']], - '-foo'=>'bar', # a trick to allow the '-' to be omitted - ref($script) eq 'ARRAY' ? @$script : %$script); - $type ||= 'text/javascript'; - unless ($type =~ m!\w+/\w+!) { - $type =~ s/[\d.]+$//; - $type = "text/$type"; - } - } else { - ($src,$code,$type) = ('',$script, 'text/javascript'); - } - - my $comment = '//'; # javascript by default - $comment = '#' if $type=~/perl|tcl/i; - $comment = "'" if $type=~/vbscript/i; - - my ($cdata_start,$cdata_end); - if ($XHTML) { - $cdata_start = "$comment<![CDATA[\n"; - $cdata_end .= "\n$comment]]>"; - } else { - $cdata_start = "\n<!-- Hide script\n"; - $cdata_end = $comment; - $cdata_end .= " End script hiding -->\n"; - } - my(@satts); - push(@satts,'src'=>$src) if $src; - push(@satts,'type'=>$type); - $code = $cdata_start . $code . $cdata_end if defined $code; - push(@result,$self->script({@satts},$code || '')); - } - @result; -} -END_OF_FUNC - -#### Method: end_html -# End an HTML document. -# Trivial method for completeness. Just returns "</body>" -#### -'end_html' => <<'END_OF_FUNC', -sub end_html { - return "\n</body>\n</html>"; -} -END_OF_FUNC - - -################################ -# METHODS USED IN BUILDING FORMS -################################ - -#### Method: isindex -# Just prints out the isindex tag. -# Parameters: -# $action -> optional URL of script to run -# Returns: -# A string containing a <isindex> tag -'isindex' => <<'END_OF_FUNC', -sub isindex { - my($self,@p) = self_or_default(@_); - my($action,@other) = rearrange([ACTION],@p); - $action = qq/ action="$action"/ if $action; - my($other) = @other ? " @other" : ''; - return $XHTML ? "<isindex$action$other />" : "<isindex$action$other>"; -} -END_OF_FUNC - - -#### Method: startform -# Start a form -# Parameters: -# $method -> optional submission method to use (GET or POST) -# $action -> optional URL of script to run -# $enctype ->encoding to use (URL_ENCODED or MULTIPART) -'startform' => <<'END_OF_FUNC', -sub startform { - my($self,@p) = self_or_default(@_); - - my($method,$action,$enctype,@other) = - rearrange([METHOD,ACTION,ENCTYPE],@p); - - $method = $self->escapeHTML(lc($method || 'post')); - $enctype = $self->escapeHTML($enctype || &URL_ENCODED); - if (defined $action) { - $action = $self->escapeHTML($action); - } - else { - $action = $self->escapeHTML($self->request_uri || $self->self_url); - } - $action = qq(action="$action"); - my($other) = @other ? " @other" : ''; - $self->{'.parametersToAdd'}={}; - return qq/<form method="$method" $action enctype="$enctype"$other>\n/; -} -END_OF_FUNC - - -#### Method: start_form -# synonym for startform -'start_form' => <<'END_OF_FUNC', -sub start_form { - $XHTML ? &start_multipart_form : &startform; -} -END_OF_FUNC - -'end_multipart_form' => <<'END_OF_FUNC', -sub end_multipart_form { - &endform; -} -END_OF_FUNC - -#### Method: start_multipart_form -# synonym for startform -'start_multipart_form' => <<'END_OF_FUNC', -sub start_multipart_form { - my($self,@p) = self_or_default(@_); - if (defined($p[0]) && substr($p[0],0,1) eq '-') { - return $self->startform(-enctype=>&MULTIPART,@p); - } else { - my($method,$action,@other) = - rearrange([METHOD,ACTION],@p); - return $self->startform($method,$action,&MULTIPART,@other); - } -} -END_OF_FUNC - - -#### Method: endform -# End a form -'endform' => <<'END_OF_FUNC', -sub endform { - my($self,@p) = self_or_default(@_); - if ( $NOSTICKY ) { - return wantarray ? ("</form>") : "\n</form>"; - } else { - if (my @fields = $self->get_fields) { - return wantarray ? ("<div>",@fields,"</div>","</form>") - : "<div>".(join '',@fields)."</div>\n</form>"; - } else { - return "</form>"; - } - } -} -END_OF_FUNC - - -'_textfield' => <<'END_OF_FUNC', -sub _textfield { - my($self,$tag,@p) = self_or_default(@_); - my($name,$default,$size,$maxlength,$override,$tabindex,@other) = - rearrange([NAME,[DEFAULT,VALUE,VALUES],SIZE,MAXLENGTH,[OVERRIDE,FORCE],TABINDEX],@p); - - my $current = $override ? $default : - (defined($self->param($name)) ? $self->param($name) : $default); - - $current = defined($current) ? $self->escapeHTML($current,1) : ''; - $name = defined($name) ? $self->escapeHTML($name) : ''; - my($s) = defined($size) ? qq/ size="$size"/ : ''; - my($m) = defined($maxlength) ? qq/ maxlength="$maxlength"/ : ''; - my($other) = @other ? " @other" : ''; - # this entered at cristy's request to fix problems with file upload fields - # and WebTV -- not sure it won't break stuff - my($value) = $current ne '' ? qq(value="$current") : ''; - $tabindex = $self->element_tab($tabindex); - return $XHTML ? qq(<input type="$tag" name="$name" $tabindex$value$s$m$other />) - : qq(<input type="$tag" name="$name" $value$s$m$other>); -} -END_OF_FUNC - -#### Method: textfield -# Parameters: -# $name -> Name of the text field -# $default -> Optional default value of the field if not -# already defined. -# $size -> Optional width of field in characaters. -# $maxlength -> Optional maximum number of characters. -# Returns: -# A string containing a <input type="text"> field -# -'textfield' => <<'END_OF_FUNC', -sub textfield { - my($self,@p) = self_or_default(@_); - $self->_textfield('text',@p); -} -END_OF_FUNC - - -#### Method: filefield -# Parameters: -# $name -> Name of the file upload field -# $size -> Optional width of field in characaters. -# $maxlength -> Optional maximum number of characters. -# Returns: -# A string containing a <input type="file"> field -# -'filefield' => <<'END_OF_FUNC', -sub filefield { - my($self,@p) = self_or_default(@_); - $self->_textfield('file',@p); -} -END_OF_FUNC - - -#### Method: password -# Create a "secret password" entry field -# Parameters: -# $name -> Name of the field -# $default -> Optional default value of the field if not -# already defined. -# $size -> Optional width of field in characters. -# $maxlength -> Optional maximum characters that can be entered. -# Returns: -# A string containing a <input type="password"> field -# -'password_field' => <<'END_OF_FUNC', -sub password_field { - my ($self,@p) = self_or_default(@_); - $self->_textfield('password',@p); -} -END_OF_FUNC - -#### Method: textarea -# Parameters: -# $name -> Name of the text field -# $default -> Optional default value of the field if not -# already defined. -# $rows -> Optional number of rows in text area -# $columns -> Optional number of columns in text area -# Returns: -# A string containing a <textarea></textarea> tag -# -'textarea' => <<'END_OF_FUNC', -sub textarea { - my($self,@p) = self_or_default(@_); - my($name,$default,$rows,$cols,$override,$tabindex,@other) = - rearrange([NAME,[DEFAULT,VALUE],ROWS,[COLS,COLUMNS],[OVERRIDE,FORCE],TABINDEX],@p); - - my($current)= $override ? $default : - (defined($self->param($name)) ? $self->param($name) : $default); - - $name = defined($name) ? $self->escapeHTML($name) : ''; - $current = defined($current) ? $self->escapeHTML($current) : ''; - my($r) = $rows ? qq/ rows="$rows"/ : ''; - my($c) = $cols ? qq/ cols="$cols"/ : ''; - my($other) = @other ? " @other" : ''; - $tabindex = $self->element_tab($tabindex); - return qq{<textarea name="$name" $tabindex$r$c$other>$current</textarea>}; -} -END_OF_FUNC - - -#### Method: button -# Create a javascript button. -# Parameters: -# $name -> (optional) Name for the button. (-name) -# $value -> (optional) Value of the button when selected (and visible name) (-value) -# $onclick -> (optional) Text of the JavaScript to run when the button is -# clicked. -# Returns: -# A string containing a <input type="button"> tag -#### -'button' => <<'END_OF_FUNC', -sub button { - my($self,@p) = self_or_default(@_); - - my($label,$value,$script,$tabindex,@other) = rearrange([NAME,[VALUE,LABEL], - [ONCLICK,SCRIPT],TABINDEX],@p); - - $label=$self->escapeHTML($label); - $value=$self->escapeHTML($value,1); - $script=$self->escapeHTML($script); - - my($name) = ''; - $name = qq/ name="$label"/ if $label; - $value = $value || $label; - my($val) = ''; - $val = qq/ value="$value"/ if $value; - $script = qq/ onclick="$script"/ if $script; - my($other) = @other ? " @other" : ''; - $tabindex = $self->element_tab($tabindex); - return $XHTML ? qq(<input type="button" $tabindex$name$val$script$other />) - : qq(<input type="button"$name$val$script$other>); -} -END_OF_FUNC - - -#### Method: submit -# Create a "submit query" button. -# Parameters: -# $name -> (optional) Name for the button. -# $value -> (optional) Value of the button when selected (also doubles as label). -# $label -> (optional) Label printed on the button(also doubles as the value). -# Returns: -# A string containing a <input type="submit"> tag -#### -'submit' => <<'END_OF_FUNC', -sub submit { - my($self,@p) = self_or_default(@_); - - my($label,$value,$tabindex,@other) = rearrange([NAME,[VALUE,LABEL],TABINDEX],@p); - - $label=$self->escapeHTML($label); - $value=$self->escapeHTML($value,1); - - my $name = $NOSTICKY ? '' : 'name=".submit" '; - $name = qq/name="$label" / if defined($label); - $value = defined($value) ? $value : $label; - my $val = ''; - $val = qq/value="$value" / if defined($value); - $tabindex = $self->element_tab($tabindex); - my($other) = @other ? "@other " : ''; - return $XHTML ? qq(<input type="submit" $tabindex$name$val$other/>) - : qq(<input type="submit" $name$val$other>); -} -END_OF_FUNC - - -#### Method: reset -# Create a "reset" button. -# Parameters: -# $name -> (optional) Name for the button. -# Returns: -# A string containing a <input type="reset"> tag -#### -'reset' => <<'END_OF_FUNC', -sub reset { - my($self,@p) = self_or_default(@_); - my($label,$value,$tabindex,@other) = rearrange(['NAME',['VALUE','LABEL'],TABINDEX],@p); - $label=$self->escapeHTML($label); - $value=$self->escapeHTML($value,1); - my ($name) = ' name=".reset"'; - $name = qq/ name="$label"/ if defined($label); - $value = defined($value) ? $value : $label; - my($val) = ''; - $val = qq/ value="$value"/ if defined($value); - my($other) = @other ? " @other" : ''; - $tabindex = $self->element_tab($tabindex); - return $XHTML ? qq(<input type="reset" $tabindex$name$val$other />) - : qq(<input type="reset"$name$val$other>); -} -END_OF_FUNC - - -#### Method: defaults -# Create a "defaults" button. -# Parameters: -# $name -> (optional) Name for the button. -# Returns: -# A string containing a <input type="submit" name=".defaults"> tag -# -# Note: this button has a special meaning to the initialization script, -# and tells it to ERASE the current query string so that your defaults -# are used again! -#### -'defaults' => <<'END_OF_FUNC', -sub defaults { - my($self,@p) = self_or_default(@_); - - my($label,$tabindex,@other) = rearrange([[NAME,VALUE],TABINDEX],@p); - - $label=$self->escapeHTML($label,1); - $label = $label || "Defaults"; - my($value) = qq/ value="$label"/; - my($other) = @other ? " @other" : ''; - $tabindex = $self->element_tab($tabindex); - return $XHTML ? qq(<input type="submit" name=".defaults" $tabindex$value$other />) - : qq/<input type="submit" NAME=".defaults"$value$other>/; -} -END_OF_FUNC - - -#### Method: comment -# Create an HTML <!-- comment --> -# Parameters: a string -'comment' => <<'END_OF_FUNC', -sub comment { - my($self,@p) = self_or_CGI(@_); - return "<!-- @p -->"; -} -END_OF_FUNC - -#### Method: checkbox -# Create a checkbox that is not logically linked to any others. -# The field value is "on" when the button is checked. -# Parameters: -# $name -> Name of the checkbox -# $checked -> (optional) turned on by default if true -# $value -> (optional) value of the checkbox, 'on' by default -# $label -> (optional) a user-readable label printed next to the box. -# Otherwise the checkbox name is used. -# Returns: -# A string containing a <input type="checkbox"> field -#### -'checkbox' => <<'END_OF_FUNC', -sub checkbox { - my($self,@p) = self_or_default(@_); - - my($name,$checked,$value,$label,$labelattributes,$override,$tabindex,@other) = - rearrange([NAME,[CHECKED,SELECTED,ON],VALUE,LABEL,LABELATTRIBUTES, - [OVERRIDE,FORCE],TABINDEX],@p); - - $value = defined $value ? $value : 'on'; - - if (!$override && ($self->{'.fieldnames'}->{$name} || - defined $self->param($name))) { - $checked = grep($_ eq $value,$self->param($name)) ? $self->_checked(1) : ''; - } else { - $checked = $self->_checked($checked); - } - my($the_label) = defined $label ? $label : $name; - $name = $self->escapeHTML($name); - $value = $self->escapeHTML($value,1); - $the_label = $self->escapeHTML($the_label); - my($other) = @other ? "@other " : ''; - $tabindex = $self->element_tab($tabindex); - $self->register_parameter($name); - return $XHTML ? CGI::label($labelattributes, - qq{<input type="checkbox" name="$name" value="$value" $tabindex$checked$other/>$the_label}) - : qq{<input type="checkbox" name="$name" value="$value"$checked$other>$the_label}; -} -END_OF_FUNC - - - -# Escape HTML -- used internally -'escapeHTML' => <<'END_OF_FUNC', -sub escapeHTML { - # hack to work around earlier hacks - push @_,$_[0] if @_==1 && $_[0] eq 'CGI'; - my ($self,$toencode,$newlinestoo) = CGI::self_or_default(@_); - return undef unless defined($toencode); - return $toencode if ref($self) && !$self->{'escape'}; - $toencode =~ s{&}{&}gso; - $toencode =~ s{<}{<}gso; - $toencode =~ s{>}{>}gso; - if ($DTD_PUBLIC_IDENTIFIER =~ /[^X]HTML 3\.2/i) { - # $quot; was accidentally omitted from the HTML 3.2 DTD -- see - # <http://validator.w3.org/docs/errors.html#bad-entity> / - # <http://lists.w3.org/Archives/Public/www-html/1997Mar/0003.html>. - $toencode =~ s{"}{"}gso; - } - else { - $toencode =~ s{"}{"}gso; - } - # Handle bug in some browsers with Latin charsets - if ($self->{'.charset'} && - (uc($self->{'.charset'}) eq 'ISO-8859-1' || - uc($self->{'.charset'}) eq 'WINDOWS-1252')) - { - $toencode =~ s{'}{'}gso; - $toencode =~ s{\x8b}{‹}gso; - $toencode =~ s{\x9b}{›}gso; - if (defined $newlinestoo && $newlinestoo) { - $toencode =~ s{\012}{ }gso; - $toencode =~ s{\015}{ }gso; - } - } - return $toencode; -} -END_OF_FUNC - -# unescape HTML -- used internally -'unescapeHTML' => <<'END_OF_FUNC', -sub unescapeHTML { - # hack to work around earlier hacks - push @_,$_[0] if @_==1 && $_[0] eq 'CGI'; - my ($self,$string) = CGI::self_or_default(@_); - return undef unless defined($string); - my $latin = defined $self->{'.charset'} ? $self->{'.charset'} =~ /^(ISO-8859-1|WINDOWS-1252)$/i - : 1; - # thanks to Randal Schwartz for the correct solution to this one - $string=~ s[&(.*?);]{ - local $_ = $1; - /^amp$/i ? "&" : - /^quot$/i ? '"' : - /^gt$/i ? ">" : - /^lt$/i ? "<" : - /^#(\d+)$/ && $latin ? chr($1) : - /^#x([0-9a-f]+)$/i && $latin ? chr(hex($1)) : - $_ - }gex; - return $string; -} -END_OF_FUNC - -# Internal procedure - don't use -'_tableize' => <<'END_OF_FUNC', -sub _tableize { - my($rows,$columns,$rowheaders,$colheaders,@elements) = @_; - my @rowheaders = $rowheaders ? @$rowheaders : (); - my @colheaders = $colheaders ? @$colheaders : (); - my($result); - - if (defined($columns)) { - $rows = int(0.99 + @elements/$columns) unless defined($rows); - } - if (defined($rows)) { - $columns = int(0.99 + @elements/$rows) unless defined($columns); - } - - # rearrange into a pretty table - $result = "<table>"; - my($row,$column); - unshift(@colheaders,'') if @colheaders && @rowheaders; - $result .= "<tr>" if @colheaders; - for (@colheaders) { - $result .= "<th>$_</th>"; - } - for ($row=0;$row<$rows;$row++) { - $result .= "<tr>"; - $result .= "<th>$rowheaders[$row]</th>" if @rowheaders; - for ($column=0;$column<$columns;$column++) { - $result .= "<td>" . $elements[$column*$rows + $row] . "</td>" - if defined($elements[$column*$rows + $row]); - } - $result .= "</tr>"; - } - $result .= "</table>"; - return $result; -} -END_OF_FUNC - - -#### Method: radio_group -# Create a list of logically-linked radio buttons. -# Parameters: -# $name -> Common name for all the buttons. -# $values -> A pointer to a regular array containing the -# values for each button in the group. -# $default -> (optional) Value of the button to turn on by default. Pass '-' -# to turn _nothing_ on. -# $linebreak -> (optional) Set to true to place linebreaks -# between the buttons. -# $labels -> (optional) -# A pointer to a hash of labels to print next to each checkbox -# in the form $label{'value'}="Long explanatory label". -# Otherwise the provided values are used as the labels. -# Returns: -# An ARRAY containing a series of <input type="radio"> fields -#### -'radio_group' => <<'END_OF_FUNC', -sub radio_group { - my($self,@p) = self_or_default(@_); - $self->_box_group('radio',@p); -} -END_OF_FUNC - -#### Method: checkbox_group -# Create a list of logically-linked checkboxes. -# Parameters: -# $name -> Common name for all the check boxes -# $values -> A pointer to a regular array containing the -# values for each checkbox in the group. -# $defaults -> (optional) -# 1. If a pointer to a regular array of checkbox values, -# then this will be used to decide which -# checkboxes to turn on by default. -# 2. If a scalar, will be assumed to hold the -# value of a single checkbox in the group to turn on. -# $linebreak -> (optional) Set to true to place linebreaks -# between the buttons. -# $labels -> (optional) -# A pointer to a hash of labels to print next to each checkbox -# in the form $label{'value'}="Long explanatory label". -# Otherwise the provided values are used as the labels. -# Returns: -# An ARRAY containing a series of <input type="checkbox"> fields -#### - -'checkbox_group' => <<'END_OF_FUNC', -sub checkbox_group { - my($self,@p) = self_or_default(@_); - $self->_box_group('checkbox',@p); -} -END_OF_FUNC - -'_box_group' => <<'END_OF_FUNC', -sub _box_group { - my $self = shift; - my $box_type = shift; - - my($name,$values,$defaults,$linebreak,$labels,$labelattributes, - $attributes,$rows,$columns,$rowheaders,$colheaders, - $override,$nolabels,$tabindex,$disabled,@other) = - rearrange([NAME,[VALUES,VALUE],[DEFAULT,DEFAULTS],LINEBREAK,LABELS,LABELATTRIBUTES, - ATTRIBUTES,ROWS,[COLUMNS,COLS],[ROWHEADERS,ROWHEADER],[COLHEADERS,COLHEADER], - [OVERRIDE,FORCE],NOLABELS,TABINDEX,DISABLED - ],@_); - - - my($result,$checked,@elements,@values); - - @values = $self->_set_values_and_labels($values,\$labels,$name); - my %checked = $self->previous_or_default($name,$defaults,$override); - - # If no check array is specified, check the first by default - $checked{$values[0]}++ if $box_type eq 'radio' && !%checked; - - $name=$self->escapeHTML($name); - - my %tabs = (); - if ($TABINDEX && $tabindex) { - if (!ref $tabindex) { - $self->element_tab($tabindex); - } elsif (ref $tabindex eq 'ARRAY') { - %tabs = map {$_=>$self->element_tab} @$tabindex; - } elsif (ref $tabindex eq 'HASH') { - %tabs = %$tabindex; - } - } - %tabs = map {$_=>$self->element_tab} @values unless %tabs; - my $other = @other ? "@other " : ''; - my $radio_checked; - - # for disabling groups of radio/checkbox buttons - my %disabled; - for (@{$disabled}) { - $disabled{$_}=1; - } - - for (@values) { - my $disable=""; - if ($disabled{$_}) { - $disable="disabled='1'"; - } - - my $checkit = $self->_checked($box_type eq 'radio' ? ($checked{$_} && !$radio_checked++) - : $checked{$_}); - my($break); - if ($linebreak) { - $break = $XHTML ? "<br />" : "<br>"; - } - else { - $break = ''; - } - my($label)=''; - unless (defined($nolabels) && $nolabels) { - $label = $_; - $label = $labels->{$_} if defined($labels) && defined($labels->{$_}); - $label = $self->escapeHTML($label,1); - $label = "<span style=\"color:gray\">$label</span>" if $disabled{$_}; - } - my $attribs = $self->_set_attributes($_, $attributes); - my $tab = $tabs{$_}; - $_=$self->escapeHTML($_); - - if ($XHTML) { - push @elements, - CGI::label($labelattributes, - qq(<input type="$box_type" name="$name" value="$_" $checkit$other$tab$attribs$disable/>$label)).${break}; - } else { - push(@elements,qq/<input type="$box_type" name="$name" value="$_"$checkit$other$tab$attribs$disable>${label}${break}/); - } - } - $self->register_parameter($name); - return wantarray ? @elements : "@elements" - unless defined($columns) || defined($rows); - return _tableize($rows,$columns,$rowheaders,$colheaders,@elements); -} -END_OF_FUNC - - -#### Method: popup_menu -# Create a popup menu. -# Parameters: -# $name -> Name for all the menu -# $values -> A pointer to a regular array containing the -# text of each menu item. -# $default -> (optional) Default item to display -# $labels -> (optional) -# A pointer to a hash of labels to print next to each checkbox -# in the form $label{'value'}="Long explanatory label". -# Otherwise the provided values are used as the labels. -# Returns: -# A string containing the definition of a popup menu. -#### -'popup_menu' => <<'END_OF_FUNC', -sub popup_menu { - my($self,@p) = self_or_default(@_); - - my($name,$values,$default,$labels,$attributes,$override,$tabindex,@other) = - rearrange([NAME,[VALUES,VALUE],[DEFAULT,DEFAULTS],LABELS, - ATTRIBUTES,[OVERRIDE,FORCE],TABINDEX],@p); - my($result,%selected); - - if (!$override && defined($self->param($name))) { - $selected{$self->param($name)}++; - } elsif (defined $default) { - %selected = map {$_=>1} ref($default) eq 'ARRAY' - ? @$default - : $default; - } - $name=$self->escapeHTML($name); - my($other) = @other ? " @other" : ''; - - my(@values); - @values = $self->_set_values_and_labels($values,\$labels,$name); - $tabindex = $self->element_tab($tabindex); - $result = qq/<select name="$name" $tabindex$other>\n/; - for (@values) { - if (/<optgroup/) { - for my $v (split(/\n/)) { - my $selectit = $XHTML ? 'selected="selected"' : 'selected'; - for my $selected (keys %selected) { - $v =~ s/(value="$selected")/$selectit $1/; - } - $result .= "$v\n"; - } - } - else { - my $attribs = $self->_set_attributes($_, $attributes); - my($selectit) = $self->_selected($selected{$_}); - my($label) = $_; - $label = $labels->{$_} if defined($labels) && defined($labels->{$_}); - my($value) = $self->escapeHTML($_); - $label = $self->escapeHTML($label,1); - $result .= "<option${attribs} ${selectit}value=\"$value\">$label</option>\n"; - } - } - - $result .= "</select>"; - return $result; -} -END_OF_FUNC - - -#### Method: optgroup -# Create a optgroup. -# Parameters: -# $name -> Label for the group -# $values -> A pointer to a regular array containing the -# values for each option line in the group. -# $labels -> (optional) -# A pointer to a hash of labels to print next to each item -# in the form $label{'value'}="Long explanatory label". -# Otherwise the provided values are used as the labels. -# $labeled -> (optional) -# A true value indicates the value should be used as the label attribute -# in the option elements. -# The label attribute specifies the option label presented to the user. -# This defaults to the content of the <option> element, but the label -# attribute allows authors to more easily use optgroup without sacrificing -# compatibility with browsers that do not support option groups. -# $novals -> (optional) -# A true value indicates to suppress the val attribute in the option elements -# Returns: -# A string containing the definition of an option group. -#### -'optgroup' => <<'END_OF_FUNC', -sub optgroup { - my($self,@p) = self_or_default(@_); - my($name,$values,$attributes,$labeled,$noval,$labels,@other) - = rearrange([NAME,[VALUES,VALUE],ATTRIBUTES,LABELED,NOVALS,LABELS],@p); - - my($result,@values); - @values = $self->_set_values_and_labels($values,\$labels,$name,$labeled,$novals); - my($other) = @other ? " @other" : ''; - - $name=$self->escapeHTML($name); - $result = qq/<optgroup label="$name"$other>\n/; - for (@values) { - if (/<optgroup/) { - for (split(/\n/)) { - my $selectit = $XHTML ? 'selected="selected"' : 'selected'; - s/(value="$selected")/$selectit $1/ if defined $selected; - $result .= "$_\n"; - } - } - else { - my $attribs = $self->_set_attributes($_, $attributes); - my($label) = $_; - $label = $labels->{$_} if defined($labels) && defined($labels->{$_}); - $label=$self->escapeHTML($label); - my($value)=$self->escapeHTML($_,1); - $result .= $labeled ? $novals ? "<option$attribs label=\"$value\">$label</option>\n" - : "<option$attribs label=\"$value\" value=\"$value\">$label</option>\n" - : $novals ? "<option$attribs>$label</option>\n" - : "<option$attribs value=\"$value\">$label</option>\n"; - } - } - $result .= "</optgroup>"; - return $result; -} -END_OF_FUNC - - -#### Method: scrolling_list -# Create a scrolling list. -# Parameters: -# $name -> name for the list -# $values -> A pointer to a regular array containing the -# values for each option line in the list. -# $defaults -> (optional) -# 1. If a pointer to a regular array of options, -# then this will be used to decide which -# lines to turn on by default. -# 2. Otherwise holds the value of the single line to turn on. -# $size -> (optional) Size of the list. -# $multiple -> (optional) If set, allow multiple selections. -# $labels -> (optional) -# A pointer to a hash of labels to print next to each checkbox -# in the form $label{'value'}="Long explanatory label". -# Otherwise the provided values are used as the labels. -# Returns: -# A string containing the definition of a scrolling list. -#### -'scrolling_list' => <<'END_OF_FUNC', -sub scrolling_list { - my($self,@p) = self_or_default(@_); - my($name,$values,$defaults,$size,$multiple,$labels,$attributes,$override,$tabindex,@other) - = rearrange([NAME,[VALUES,VALUE],[DEFAULTS,DEFAULT], - SIZE,MULTIPLE,LABELS,ATTRIBUTES,[OVERRIDE,FORCE],TABINDEX],@p); - - my($result,@values); - @values = $self->_set_values_and_labels($values,\$labels,$name); - - $size = $size || scalar(@values); - - my(%selected) = $self->previous_or_default($name,$defaults,$override); - - my($is_multiple) = $multiple ? qq/ multiple="multiple"/ : ''; - my($has_size) = $size ? qq/ size="$size"/: ''; - my($other) = @other ? " @other" : ''; - - $name=$self->escapeHTML($name); - $tabindex = $self->element_tab($tabindex); - $result = qq/<select name="$name" $tabindex$has_size$is_multiple$other>\n/; - for (@values) { - if (/<optgroup/) { - for my $v (split(/\n/)) { - my $selectit = $XHTML ? 'selected="selected"' : 'selected'; - for my $selected (keys %selected) { - $v =~ s/(value="$selected")/$selectit $1/; - } - $result .= "$v\n"; - } - } - else { - my $attribs = $self->_set_attributes($_, $attributes); - my($selectit) = $self->_selected($selected{$_}); - my($label) = $_; - $label = $labels->{$_} if defined($labels) && defined($labels->{$_}); - my($value) = $self->escapeHTML($_); - $label = $self->escapeHTML($label,1); - $result .= "<option${attribs} ${selectit}value=\"$value\">$label</option>\n"; - } - } - - $result .= "</select>"; - $self->register_parameter($name); - return $result; -} -END_OF_FUNC - - -#### Method: hidden -# Parameters: -# $name -> Name of the hidden field -# @default -> (optional) Initial values of field (may be an array) -# or -# $default->[initial values of field] -# Returns: -# A string containing a <input type="hidden" name="name" value="value"> -#### -'hidden' => <<'END_OF_FUNC', -sub hidden { - my($self,@p) = self_or_default(@_); - - # this is the one place where we departed from our standard - # calling scheme, so we have to special-case (darn) - my(@result,@value); - my($name,$default,$override,@other) = - rearrange([NAME,[DEFAULT,VALUE,VALUES],[OVERRIDE,FORCE]],@p); - - my $do_override = 0; - if ( ref($p[0]) || substr($p[0],0,1) eq '-') { - @value = ref($default) ? @{$default} : $default; - $do_override = $override; - } else { - for ($default,$override,@other) { - push(@value,$_) if defined($_); - } - } - - # use previous values if override is not set - my @prev = $self->param($name); - @value = @prev if !$do_override && @prev; - - $name=$self->escapeHTML($name); - for (@value) { - $_ = defined($_) ? $self->escapeHTML($_,1) : ''; - push @result,$XHTML ? qq(<input type="hidden" name="$name" value="$_" @other />) - : qq(<input type="hidden" name="$name" value="$_" @other>); - } - return wantarray ? @result : join('',@result); -} -END_OF_FUNC - - -#### Method: image_button -# Parameters: -# $name -> Name of the button -# $src -> URL of the image source -# $align -> Alignment style (TOP, BOTTOM or MIDDLE) -# Returns: -# A string containing a <input type="image" name="name" src="url" align="alignment"> -#### -'image_button' => <<'END_OF_FUNC', -sub image_button { - my($self,@p) = self_or_default(@_); - - my($name,$src,$alignment,@other) = - rearrange([NAME,SRC,ALIGN],@p); - - my($align) = $alignment ? " align=\L\"$alignment\"" : ''; - my($other) = @other ? " @other" : ''; - $name=$self->escapeHTML($name); - return $XHTML ? qq(<input type="image" name="$name" src="$src"$align$other />) - : qq/<input type="image" name="$name" src="$src"$align$other>/; -} -END_OF_FUNC - - -#### Method: self_url -# Returns a URL containing the current script and all its -# param/value pairs arranged as a query. You can use this -# to create a link that, when selected, will reinvoke the -# script with all its state information preserved. -#### -'self_url' => <<'END_OF_FUNC', -sub self_url { - my($self,@p) = self_or_default(@_); - return $self->url('-path_info'=>1,'-query'=>1,'-full'=>1,@p); -} -END_OF_FUNC - - -# This is provided as a synonym to self_url() for people unfortunate -# enough to have incorporated it into their programs already! -'state' => <<'END_OF_FUNC', -sub state { - &self_url; -} -END_OF_FUNC - - -#### Method: url -# Like self_url, but doesn't return the query string part of -# the URL. -#### -'url' => <<'END_OF_FUNC', -sub url { - my($self,@p) = self_or_default(@_); - my ($relative,$absolute,$full,$path_info,$query,$base,$rewrite) = - rearrange(['RELATIVE','ABSOLUTE','FULL',['PATH','PATH_INFO'],['QUERY','QUERY_STRING'],'BASE','REWRITE'],@p); - my $url = ''; - $full++ if $base || !($relative || $absolute); - $rewrite++ unless defined $rewrite; - - my $path = $self->path_info; - my $script_name = $self->script_name; - my $request_uri = unescape($self->request_uri) || ''; - my $query_str = $self->query_string; - - my $rewrite_in_use = $request_uri && $request_uri !~ /^\Q$script_name/; - undef $path if $rewrite_in_use && $rewrite; # path not valid when rewriting active - - my $uri = $rewrite && $request_uri ? $request_uri : $script_name; - $uri =~ s/\?.*$//s; # remove query string - $uri =~ s/\Q$ENV{PATH_INFO}\E$// if defined $ENV{PATH_INFO}; -# $uri =~ s/\Q$path\E$// if defined $path; # remove path - - if ($full) { - my $protocol = $self->protocol(); - $url = "$protocol://"; - my $vh = http('x_forwarded_host') || http('host') || ''; - $vh =~ s/\:\d+$//; # some clients add the port number (incorrectly). Get rid of it. - if ($vh) { - $url .= $vh; - } else { - $url .= server_name(); - } - my $port = $self->server_port; - $url .= ":" . $port - unless (lc($protocol) eq 'http' && $port == 80) - || (lc($protocol) eq 'https' && $port == 443); - return $url if $base; - $url .= $uri; - } elsif ($relative) { - ($url) = $uri =~ m!([^/]+)$!; - } elsif ($absolute) { - $url = $uri; - } - - $url .= $path if $path_info and defined $path; - $url .= "?$query_str" if $query and $query_str ne ''; - $url ||= ''; - $url =~ s/([^a-zA-Z0-9_.%;&?\/\\:+=~-])/sprintf("%%%02X",ord($1))/eg; - return $url; -} - -END_OF_FUNC - -#### Method: cookie -# Set or read a cookie from the specified name. -# Cookie can then be passed to header(). -# Usual rules apply to the stickiness of -value. -# Parameters: -# -name -> name for this cookie (optional) -# -value -> value of this cookie (scalar, array or hash) -# -path -> paths for which this cookie is valid (optional) -# -domain -> internet domain in which this cookie is valid (optional) -# -secure -> if true, cookie only passed through secure channel (optional) -# -expires -> expiry date in format Wdy, DD-Mon-YYYY HH:MM:SS GMT (optional) -#### -'cookie' => <<'END_OF_FUNC', -sub cookie { - my($self,@p) = self_or_default(@_); - my($name,$value,$path,$domain,$secure,$expires,$httponly) = - rearrange([NAME,[VALUE,VALUES],PATH,DOMAIN,SECURE,EXPIRES,HTTPONLY],@p); - - require CGI::Cookie; - - # if no value is supplied, then we retrieve the - # value of the cookie, if any. For efficiency, we cache the parsed - # cookies in our state variables. - unless ( defined($value) ) { - $self->{'.cookies'} = CGI::Cookie->fetch; - - # If no name is supplied, then retrieve the names of all our cookies. - return () unless $self->{'.cookies'}; - return keys %{$self->{'.cookies'}} unless $name; - return () unless $self->{'.cookies'}->{$name}; - return $self->{'.cookies'}->{$name}->value if defined($name) && $name ne ''; - } - - # If we get here, we're creating a new cookie - return undef unless defined($name) && $name ne ''; # this is an error - - my @param; - push(@param,'-name'=>$name); - push(@param,'-value'=>$value); - push(@param,'-domain'=>$domain) if $domain; - push(@param,'-path'=>$path) if $path; - push(@param,'-expires'=>$expires) if $expires; - push(@param,'-secure'=>$secure) if $secure; - push(@param,'-httponly'=>$httponly) if $httponly; - - return new CGI::Cookie(@param); -} -END_OF_FUNC - -'parse_keywordlist' => <<'END_OF_FUNC', -sub parse_keywordlist { - my($self,$tosplit) = @_; - $tosplit = unescape($tosplit); # unescape the keywords - $tosplit=~tr/+/ /; # pluses to spaces - my(@keywords) = split(/\s+/,$tosplit); - return @keywords; -} -END_OF_FUNC - -'param_fetch' => <<'END_OF_FUNC', -sub param_fetch { - my($self,@p) = self_or_default(@_); - my($name) = rearrange([NAME],@p); - unless (exists($self->{param}{$name})) { - $self->add_parameter($name); - $self->{param}{$name} = []; - } - - return $self->{param}{$name}; -} -END_OF_FUNC - -############################################### -# OTHER INFORMATION PROVIDED BY THE ENVIRONMENT -############################################### - -#### Method: path_info -# Return the extra virtual path information provided -# after the URL (if any) -#### -'path_info' => <<'END_OF_FUNC', -sub path_info { - my ($self,$info) = self_or_default(@_); - if (defined($info)) { - $info = "/$info" if $info ne '' && substr($info,0,1) ne '/'; - $self->{'.path_info'} = $info; - } elsif (! defined($self->{'.path_info'}) ) { - my (undef,$path_info) = $self->_name_and_path_from_env; - $self->{'.path_info'} = $path_info || ''; - } - return $self->{'.path_info'}; -} -END_OF_FUNC - -# This function returns a potentially modified version of SCRIPT_NAME -# and PATH_INFO. Some HTTP servers do sanitise the paths in those -# variables. It is the case of at least Apache 2. If for instance the -# user requests: /path/./to/script.cgi/x//y/z/../x?y, Apache will set: -# REQUEST_URI=/path/./to/script.cgi/x//y/z/../x?y -# SCRIPT_NAME=/path/to/env.cgi -# PATH_INFO=/x/y/x -# -# This is all fine except that some bogus CGI scripts expect -# PATH_INFO=/http://foo when the user requests -# http://xxx/script.cgi/http://foo -# -# Old versions of this module used to accomodate with those scripts, so -# this is why we do this here to keep those scripts backward compatible. -# Basically, we accomodate with those scripts but within limits, that is -# we only try to preserve the number of / that were provided by the user -# if $REQUEST_URI and "$SCRIPT_NAME$PATH_INFO" only differ by the number -# of consecutive /. -# -# So for instance, in: http://foo/x//y/script.cgi/a//b, we'll return a -# script_name of /x//y/script.cgi and a path_info of /a//b, but in: -# http://foo/./x//z/script.cgi/a/../b//c, we'll return the versions -# possibly sanitised by the HTTP server, so in the case of Apache 2: -# script_name == /foo/x/z/script.cgi and path_info == /b/c. -# -# Future versions of this module may no longer do that, so one should -# avoid relying on the browser, proxy, server, and CGI.pm preserving the -# number of consecutive slashes as no guarantee can be made there. -'_name_and_path_from_env' => <<'END_OF_FUNC', -sub _name_and_path_from_env { - my $self = shift; - my $script_name = $ENV{SCRIPT_NAME} || ''; - my $path_info = $ENV{PATH_INFO} || ''; - my $uri = $self->request_uri || ''; - - $uri =~ s/\?.*//s; - $uri = unescape($uri); - - if ($uri ne "$script_name$path_info") { - my $script_name_pattern = quotemeta($script_name); - my $path_info_pattern = quotemeta($path_info); - $script_name_pattern =~ s{(?:\\/)+}{/+}g; - $path_info_pattern =~ s{(?:\\/)+}{/+}g; - - if ($uri =~ /^($script_name_pattern)($path_info_pattern)$/s) { - # REQUEST_URI and SCRIPT_NAME . PATH_INFO only differ by the - # numer of consecutive slashes, so we can extract the info from - # REQUEST_URI: - ($script_name, $path_info) = ($1, $2); - } - } - return ($script_name,$path_info); -} -END_OF_FUNC - - -#### Method: request_method -# Returns 'POST', 'GET', 'PUT' or 'HEAD' -#### -'request_method' => <<'END_OF_FUNC', -sub request_method { - return (defined $ENV{'REQUEST_METHOD'}) ? $ENV{'REQUEST_METHOD'} : undef; -} -END_OF_FUNC - -#### Method: content_type -# Returns the content_type string -#### -'content_type' => <<'END_OF_FUNC', -sub content_type { - return (defined $ENV{'CONTENT_TYPE'}) ? $ENV{'CONTENT_TYPE'} : undef; -} -END_OF_FUNC - -#### Method: path_translated -# Return the physical path information provided -# by the URL (if any) -#### -'path_translated' => <<'END_OF_FUNC', -sub path_translated { - return (defined $ENV{'PATH_TRANSLATED'}) ? $ENV{'PATH_TRANSLATED'} : undef; -} -END_OF_FUNC - - -#### Method: request_uri -# Return the literal request URI -#### -'request_uri' => <<'END_OF_FUNC', -sub request_uri { - return (defined $ENV{'REQUEST_URI'}) ? $ENV{'REQUEST_URI'} : undef; -} -END_OF_FUNC - - -#### Method: query_string -# Synthesize a query string from our current -# parameters -#### -'query_string' => <<'END_OF_FUNC', -sub query_string { - my($self) = self_or_default(@_); - my($param,$value,@pairs); - for $param ($self->param) { - my($eparam) = escape($param); - for $value ($self->param($param)) { - $value = escape($value); - next unless defined $value; - push(@pairs,"$eparam=$value"); - } - } - for (keys %{$self->{'.fieldnames'}}) { - push(@pairs,".cgifields=".escape("$_")); - } - return join($USE_PARAM_SEMICOLONS ? ';' : '&',@pairs); -} -END_OF_FUNC - - -#### Method: accept -# Without parameters, returns an array of the -# MIME types the browser accepts. -# With a single parameter equal to a MIME -# type, will return undef if the browser won't -# accept it, 1 if the browser accepts it but -# doesn't give a preference, or a floating point -# value between 0.0 and 1.0 if the browser -# declares a quantitative score for it. -# This handles MIME type globs correctly. -#### -'Accept' => <<'END_OF_FUNC', -sub Accept { - my($self,$search) = self_or_CGI(@_); - my(%prefs,$type,$pref,$pat); - - my(@accept) = defined $self->http('accept') - ? split(',',$self->http('accept')) - : (); - - for (@accept) { - ($pref) = /q=(\d\.\d+|\d+)/; - ($type) = m#(\S+/[^;]+)#; - next unless $type; - $prefs{$type}=$pref || 1; - } - - return keys %prefs unless $search; - - # if a search type is provided, we may need to - # perform a pattern matching operation. - # The MIME types use a glob mechanism, which - # is easily translated into a perl pattern match - - # First return the preference for directly supported - # types: - return $prefs{$search} if $prefs{$search}; - - # Didn't get it, so try pattern matching. - for (keys %prefs) { - next unless /\*/; # not a pattern match - ($pat = $_) =~ s/([^\w*])/\\$1/g; # escape meta characters - $pat =~ s/\*/.*/g; # turn it into a pattern - return $prefs{$_} if $search=~/$pat/; - } -} -END_OF_FUNC - - -#### Method: user_agent -# If called with no parameters, returns the user agent. -# If called with one parameter, does a pattern match (case -# insensitive) on the user agent. -#### -'user_agent' => <<'END_OF_FUNC', -sub user_agent { - my($self,$match)=self_or_CGI(@_); - my $user_agent = $self->http('user_agent'); - return $user_agent unless $match && $user_agent; - return $user_agent =~ /$match/i; -} -END_OF_FUNC - - -#### Method: raw_cookie -# Returns the magic cookies for the session. -# The cookies are not parsed or altered in any way, i.e. -# cookies are returned exactly as given in the HTTP -# headers. If a cookie name is given, only that cookie's -# value is returned, otherwise the entire raw cookie -# is returned. -#### -'raw_cookie' => <<'END_OF_FUNC', -sub raw_cookie { - my($self,$key) = self_or_CGI(@_); - - require CGI::Cookie; - - if (defined($key)) { - $self->{'.raw_cookies'} = CGI::Cookie->raw_fetch - unless $self->{'.raw_cookies'}; - - return () unless $self->{'.raw_cookies'}; - return () unless $self->{'.raw_cookies'}->{$key}; - return $self->{'.raw_cookies'}->{$key}; - } - return $self->http('cookie') || $ENV{'COOKIE'} || ''; -} -END_OF_FUNC - -#### Method: virtual_host -# Return the name of the virtual_host, which -# is not always the same as the server -###### -'virtual_host' => <<'END_OF_FUNC', -sub virtual_host { - my $vh = http('x_forwarded_host') || http('host') || server_name(); - $vh =~ s/:\d+$//; # get rid of port number - return $vh; -} -END_OF_FUNC - -#### Method: remote_host -# Return the name of the remote host, or its IP -# address if unavailable. If this variable isn't -# defined, it returns "localhost" for debugging -# purposes. -#### -'remote_host' => <<'END_OF_FUNC', -sub remote_host { - return $ENV{'REMOTE_HOST'} || $ENV{'REMOTE_ADDR'} - || 'localhost'; -} -END_OF_FUNC - - -#### Method: remote_addr -# Return the IP addr of the remote host. -#### -'remote_addr' => <<'END_OF_FUNC', -sub remote_addr { - return $ENV{'REMOTE_ADDR'} || '127.0.0.1'; -} -END_OF_FUNC - - -#### Method: script_name -# Return the partial URL to this script for -# self-referencing scripts. Also see -# self_url(), which returns a URL with all state information -# preserved. -#### -'script_name' => <<'END_OF_FUNC', -sub script_name { - my ($self,@p) = self_or_default(@_); - if (@p) { - $self->{'.script_name'} = shift @p; - } elsif (!exists $self->{'.script_name'}) { - my ($script_name,$path_info) = $self->_name_and_path_from_env(); - $self->{'.script_name'} = $script_name; - } - return $self->{'.script_name'}; -} -END_OF_FUNC - - -#### Method: referer -# Return the HTTP_REFERER: useful for generating -# a GO BACK button. -#### -'referer' => <<'END_OF_FUNC', -sub referer { - my($self) = self_or_CGI(@_); - return $self->http('referer'); -} -END_OF_FUNC - - -#### Method: server_name -# Return the name of the server -#### -'server_name' => <<'END_OF_FUNC', -sub server_name { - return $ENV{'SERVER_NAME'} || 'localhost'; -} -END_OF_FUNC - -#### Method: server_software -# Return the name of the server software -#### -'server_software' => <<'END_OF_FUNC', -sub server_software { - return $ENV{'SERVER_SOFTWARE'} || 'cmdline'; -} -END_OF_FUNC - -#### Method: virtual_port -# Return the server port, taking virtual hosts into account -#### -'virtual_port' => <<'END_OF_FUNC', -sub virtual_port { - my($self) = self_or_default(@_); - my $vh = $self->http('x_forwarded_host') || $self->http('host'); - my $protocol = $self->protocol; - if ($vh) { - return ($vh =~ /:(\d+)$/)[0] || ($protocol eq 'https' ? 443 : 80); - } else { - return $self->server_port(); - } -} -END_OF_FUNC - -#### Method: server_port -# Return the tcp/ip port the server is running on -#### -'server_port' => <<'END_OF_FUNC', -sub server_port { - return $ENV{'SERVER_PORT'} || 80; # for debugging -} -END_OF_FUNC - -#### Method: server_protocol -# Return the protocol (usually HTTP/1.0) -#### -'server_protocol' => <<'END_OF_FUNC', -sub server_protocol { - return $ENV{'SERVER_PROTOCOL'} || 'HTTP/1.0'; # for debugging -} -END_OF_FUNC - -#### Method: http -# Return the value of an HTTP variable, or -# the list of variables if none provided -#### -'http' => <<'END_OF_FUNC', -sub http { - my ($self,$parameter) = self_or_CGI(@_); - if ( defined($parameter) ) { - if ( $parameter =~ /^HTTP/ ) { - return $ENV{$parameter}; - } - $parameter =~ tr/-/_/; - } - return $ENV{"HTTP_\U$parameter\E"} if $parameter; - my(@p); - for (keys %ENV) { - push(@p,$_) if /^HTTP/; - } - return @p; -} -END_OF_FUNC - -#### Method: https -# Return the value of HTTPS -#### -'https' => <<'END_OF_FUNC', -sub https { - local($^W)=0; - my ($self,$parameter) = self_or_CGI(@_); - return $ENV{HTTPS} unless $parameter; - return $ENV{$parameter} if $parameter=~/^HTTPS/; - $parameter =~ tr/-/_/; - return $ENV{"HTTPS_\U$parameter\E"} if $parameter; - my(@p); - for (keys %ENV) { - push(@p,$_) if /^HTTPS/; - } - return @p; -} -END_OF_FUNC - -#### Method: protocol -# Return the protocol (http or https currently) -#### -'protocol' => <<'END_OF_FUNC', -sub protocol { - local($^W)=0; - my $self = shift; - return 'https' if uc($self->https()) eq 'ON'; - return 'https' if $self->server_port == 443; - my $prot = $self->server_protocol; - my($protocol,$version) = split('/',$prot); - return "\L$protocol\E"; -} -END_OF_FUNC - -#### Method: remote_ident -# Return the identity of the remote user -# (but only if his host is running identd) -#### -'remote_ident' => <<'END_OF_FUNC', -sub remote_ident { - return (defined $ENV{'REMOTE_IDENT'}) ? $ENV{'REMOTE_IDENT'} : undef; -} -END_OF_FUNC - - -#### Method: auth_type -# Return the type of use verification/authorization in use, if any. -#### -'auth_type' => <<'END_OF_FUNC', -sub auth_type { - return (defined $ENV{'AUTH_TYPE'}) ? $ENV{'AUTH_TYPE'} : undef; -} -END_OF_FUNC - - -#### Method: remote_user -# Return the authorization name used for user -# verification. -#### -'remote_user' => <<'END_OF_FUNC', -sub remote_user { - return (defined $ENV{'REMOTE_USER'}) ? $ENV{'REMOTE_USER'} : undef; -} -END_OF_FUNC - - -#### Method: user_name -# Try to return the remote user's name by hook or by -# crook -#### -'user_name' => <<'END_OF_FUNC', -sub user_name { - my ($self) = self_or_CGI(@_); - return $self->http('from') || $ENV{'REMOTE_IDENT'} || $ENV{'REMOTE_USER'}; -} -END_OF_FUNC - -#### Method: nosticky -# Set or return the NOSTICKY global flag -#### -'nosticky' => <<'END_OF_FUNC', -sub nosticky { - my ($self,$param) = self_or_CGI(@_); - $CGI::NOSTICKY = $param if defined($param); - return $CGI::NOSTICKY; -} -END_OF_FUNC - -#### Method: nph -# Set or return the NPH global flag -#### -'nph' => <<'END_OF_FUNC', -sub nph { - my ($self,$param) = self_or_CGI(@_); - $CGI::NPH = $param if defined($param); - return $CGI::NPH; -} -END_OF_FUNC - -#### Method: private_tempfiles -# Set or return the private_tempfiles global flag -#### -'private_tempfiles' => <<'END_OF_FUNC', -sub private_tempfiles { - my ($self,$param) = self_or_CGI(@_); - $CGI::PRIVATE_TEMPFILES = $param if defined($param); - return $CGI::PRIVATE_TEMPFILES; -} -END_OF_FUNC -#### Method: close_upload_files -# Set or return the close_upload_files global flag -#### -'close_upload_files' => <<'END_OF_FUNC', -sub close_upload_files { - my ($self,$param) = self_or_CGI(@_); - $CGI::CLOSE_UPLOAD_FILES = $param if defined($param); - return $CGI::CLOSE_UPLOAD_FILES; -} -END_OF_FUNC - - -#### Method: default_dtd -# Set or return the default_dtd global -#### -'default_dtd' => <<'END_OF_FUNC', -sub default_dtd { - my ($self,$param,$param2) = self_or_CGI(@_); - if (defined $param2 && defined $param) { - $CGI::DEFAULT_DTD = [ $param, $param2 ]; - } elsif (defined $param) { - $CGI::DEFAULT_DTD = $param; - } - return $CGI::DEFAULT_DTD; -} -END_OF_FUNC - -# -------------- really private subroutines ----------------- -'previous_or_default' => <<'END_OF_FUNC', -sub previous_or_default { - my($self,$name,$defaults,$override) = @_; - my(%selected); - - if (!$override && ($self->{'.fieldnames'}->{$name} || - defined($self->param($name)) ) ) { - $selected{$_}++ for $self->param($name); - } elsif (defined($defaults) && ref($defaults) && - (ref($defaults) eq 'ARRAY')) { - $selected{$_}++ for @{$defaults}; - } else { - $selected{$defaults}++ if defined($defaults); - } - - return %selected; -} -END_OF_FUNC - -'register_parameter' => <<'END_OF_FUNC', -sub register_parameter { - my($self,$param) = @_; - $self->{'.parametersToAdd'}->{$param}++; -} -END_OF_FUNC - -'get_fields' => <<'END_OF_FUNC', -sub get_fields { - my($self) = @_; - return $self->CGI::hidden('-name'=>'.cgifields', - '-values'=>[keys %{$self->{'.parametersToAdd'}}], - '-override'=>1); -} -END_OF_FUNC - -'read_from_cmdline' => <<'END_OF_FUNC', -sub read_from_cmdline { - my($input,@words); - my($query_string); - my($subpath); - if ($DEBUG && @ARGV) { - @words = @ARGV; - } elsif ($DEBUG > 1) { - require "shellwords.pl"; - print STDERR "(offline mode: enter name=value pairs on standard input; press ^D or ^Z when done)\n"; - chomp(@lines = <STDIN>); # remove newlines - $input = join(" ",@lines); - @words = &shellwords($input); - } - for (@words) { - s/\\=/%3D/g; - s/\\&/%26/g; - } - - if ("@words"=~/=/) { - $query_string = join('&',@words); - } else { - $query_string = join('+',@words); - } - if ($query_string =~ /^(.*?)\?(.*)$/) - { - $query_string = $2; - $subpath = $1; - } - return { 'query_string' => $query_string, 'subpath' => $subpath }; -} -END_OF_FUNC - -##### -# subroutine: read_multipart -# -# Read multipart data and store it into our parameters. -# An interesting feature is that if any of the parts is a file, we -# create a temporary file and open up a filehandle on it so that the -# caller can read from it if necessary. -##### -'read_multipart' => <<'END_OF_FUNC', -sub read_multipart { - my($self,$boundary,$length) = @_; - my($buffer) = $self->new_MultipartBuffer($boundary,$length); - return unless $buffer; - my(%header,$body); - my $filenumber = 0; - while (!$buffer->eof) { - %header = $buffer->readHeader; - - unless (%header) { - $self->cgi_error("400 Bad request (malformed multipart POST)"); - return; - } - - $header{'Content-Disposition'} ||= ''; # quench uninit variable warning - - my($param)= $header{'Content-Disposition'}=~/[\s;]name="([^"]*)"/; - $param .= $TAINTED; - - # See RFC 1867, 2183, 2045 - # NB: File content will be loaded into memory should - # content-disposition parsing fail. - my ($filename) = $header{'Content-Disposition'} - =~/ filename=(("[^"]*")|([a-z\d!\#'\*\+,\.^_\`\{\}\|\~]*))/i; - - $filename ||= ''; # quench uninit variable warning - - $filename =~ s/^"([^"]*)"$/$1/; - # Test for Opera's multiple upload feature - my($multipart) = ( defined( $header{'Content-Type'} ) && - $header{'Content-Type'} =~ /multipart\/mixed/ ) ? - 1 : 0; - - # add this parameter to our list - $self->add_parameter($param); - - # If no filename specified, then just read the data and assign it - # to our parameter list. - if ( ( !defined($filename) || $filename eq '' ) && !$multipart ) { - my($value) = $buffer->readBody; - $value .= $TAINTED; - push(@{$self->{param}{$param}},$value); - next; - } - - my ($tmpfile,$tmp,$filehandle); - UPLOADS: { - # If we get here, then we are dealing with a potentially large - # uploaded form. Save the data to a temporary file, then open - # the file for reading. - - # skip the file if uploads disabled - if ($DISABLE_UPLOADS) { - while (defined($data = $buffer->read)) { } - last UPLOADS; - } - - # set the filename to some recognizable value - if ( ( !defined($filename) || $filename eq '' ) && $multipart ) { - $filename = "multipart/mixed"; - } - - # choose a relatively unpredictable tmpfile sequence number - my $seqno = unpack("%16C*",join('',localtime,grep {defined $_} values %ENV)); - for (my $cnt=10;$cnt>0;$cnt--) { - next unless $tmpfile = new CGITempFile($seqno); - $tmp = $tmpfile->as_string; - last if defined($filehandle = Fh->new($filename,$tmp,$PRIVATE_TEMPFILES)); - $seqno += int rand(100); - } - die "CGI open of tmpfile: $!\n" unless defined $filehandle; - $CGI::DefaultClass->binmode($filehandle) if $CGI::needs_binmode - && defined fileno($filehandle); - - # if this is an multipart/mixed attachment, save the header - # together with the body for later parsing with an external - # MIME parser module - if ( $multipart ) { - for ( keys %header ) { - print $filehandle "$_: $header{$_}${CRLF}"; - } - print $filehandle "${CRLF}"; - } - - my ($data); - local($\) = ''; - my $totalbytes = 0; - while (defined($data = $buffer->read)) { - if (defined $self->{'.upload_hook'}) - { - $totalbytes += length($data); - &{$self->{'.upload_hook'}}($filename ,$data, $totalbytes, $self->{'.upload_data'}); - } - print $filehandle $data if ($self->{'use_tempfile'}); - } - - # back up to beginning of file - seek($filehandle,0,0); - - ## Close the filehandle if requested this allows a multipart MIME - ## upload to contain many files, and we won't die due to too many - ## open file handles. The user can access the files using the hash - ## below. - close $filehandle if $CLOSE_UPLOAD_FILES; - $CGI::DefaultClass->binmode($filehandle) if $CGI::needs_binmode; - - # Save some information about the uploaded file where we can get - # at it later. - # Use the typeglob as the key, as this is guaranteed to be - # unique for each filehandle. Don't use the file descriptor as - # this will be re-used for each filehandle if the - # close_upload_files feature is used. - $self->{'.tmpfiles'}->{$$filehandle}= { - hndl => $filehandle, - name => $tmpfile, - info => {%header}, - }; - push(@{$self->{param}{$param}},$filehandle); - } - } -} -END_OF_FUNC - -##### -# subroutine: read_multipart_related -# -# Read multipart/related data and store it into our parameters. The -# first parameter sets the start of the data. The part identified by -# this Content-ID will not be stored as a file upload, but will be -# returned by this method. All other parts will be available as file -# uploads accessible by their Content-ID -##### -'read_multipart_related' => <<'END_OF_FUNC', -sub read_multipart_related { - my($self,$start,$boundary,$length) = @_; - my($buffer) = $self->new_MultipartBuffer($boundary,$length); - return unless $buffer; - my(%header,$body); - my $filenumber = 0; - my $returnvalue; - while (!$buffer->eof) { - %header = $buffer->readHeader; - - unless (%header) { - $self->cgi_error("400 Bad request (malformed multipart POST)"); - return; - } - - my($param) = $header{'Content-ID'}=~/\<([^\>]*)\>/; - $param .= $TAINTED; - - # If this is the start part, then just read the data and assign it - # to our return variable. - if ( $param eq $start ) { - $returnvalue = $buffer->readBody; - $returnvalue .= $TAINTED; - next; - } - - # add this parameter to our list - $self->add_parameter($param); - - my ($tmpfile,$tmp,$filehandle); - UPLOADS: { - # If we get here, then we are dealing with a potentially large - # uploaded form. Save the data to a temporary file, then open - # the file for reading. - - # skip the file if uploads disabled - if ($DISABLE_UPLOADS) { - while (defined($data = $buffer->read)) { } - last UPLOADS; - } - - # choose a relatively unpredictable tmpfile sequence number - my $seqno = unpack("%16C*",join('',localtime,grep {defined $_} values %ENV)); - for (my $cnt=10;$cnt>0;$cnt--) { - next unless $tmpfile = new CGITempFile($seqno); - $tmp = $tmpfile->as_string; - last if defined($filehandle = Fh->new($param,$tmp,$PRIVATE_TEMPFILES)); - $seqno += int rand(100); - } - die "CGI open of tmpfile: $!\n" unless defined $filehandle; - $CGI::DefaultClass->binmode($filehandle) if $CGI::needs_binmode - && defined fileno($filehandle); - - my ($data); - local($\) = ''; - my $totalbytes; - while (defined($data = $buffer->read)) { - if (defined $self->{'.upload_hook'}) - { - $totalbytes += length($data); - &{$self->{'.upload_hook'}}($param ,$data, $totalbytes, $self->{'.upload_data'}); - } - print $filehandle $data if ($self->{'use_tempfile'}); - } - - # back up to beginning of file - seek($filehandle,0,0); - - ## Close the filehandle if requested this allows a multipart MIME - ## upload to contain many files, and we won't die due to too many - ## open file handles. The user can access the files using the hash - ## below. - close $filehandle if $CLOSE_UPLOAD_FILES; - $CGI::DefaultClass->binmode($filehandle) if $CGI::needs_binmode; - - # Save some information about the uploaded file where we can get - # at it later. - # Use the typeglob as the key, as this is guaranteed to be - # unique for each filehandle. Don't use the file descriptor as - # this will be re-used for each filehandle if the - # close_upload_files feature is used. - $self->{'.tmpfiles'}->{$$filehandle}= { - hndl => $filehandle, - name => $tmpfile, - info => {%header}, - }; - push(@{$self->{param}{$param}},$filehandle); - } - } - return $returnvalue; -} -END_OF_FUNC - - -'upload' =><<'END_OF_FUNC', -sub upload { - my($self,$param_name) = self_or_default(@_); - my @param = grep {ref($_) && defined(fileno($_))} $self->param($param_name); - return unless @param; - return wantarray ? @param : $param[0]; -} -END_OF_FUNC - -'tmpFileName' => <<'END_OF_FUNC', -sub tmpFileName { - my($self,$filename) = self_or_default(@_); - return $self->{'.tmpfiles'}->{$$filename}->{name} ? - $self->{'.tmpfiles'}->{$$filename}->{name}->as_string - : ''; -} -END_OF_FUNC - -'uploadInfo' => <<'END_OF_FUNC', -sub uploadInfo { - my($self,$filename) = self_or_default(@_); - return $self->{'.tmpfiles'}->{$$filename}->{info}; -} -END_OF_FUNC - -# internal routine, don't use -'_set_values_and_labels' => <<'END_OF_FUNC', -sub _set_values_and_labels { - my $self = shift; - my ($v,$l,$n) = @_; - $$l = $v if ref($v) eq 'HASH' && !ref($$l); - return $self->param($n) if !defined($v); - return $v if !ref($v); - return ref($v) eq 'HASH' ? keys %$v : @$v; -} -END_OF_FUNC - -# internal routine, don't use -'_set_attributes' => <<'END_OF_FUNC', -sub _set_attributes { - my $self = shift; - my($element, $attributes) = @_; - return '' unless defined($attributes->{$element}); - $attribs = ' '; - for my $attrib (keys %{$attributes->{$element}}) { - (my $clean_attrib = $attrib) =~ s/^-//; - $attribs .= "@{[lc($clean_attrib)]}=\"$attributes->{$element}{$attrib}\" "; - } - $attribs =~ s/ $//; - return $attribs; -} -END_OF_FUNC - -'_compile_all' => <<'END_OF_FUNC', -sub _compile_all { - for (@_) { - next if defined(&$_); - $AUTOLOAD = "CGI::$_"; - _compile(); - } -} -END_OF_FUNC - -); -END_OF_AUTOLOAD -; - -######################################################### -# Globals and stubs for other packages that we use. -######################################################### - -################### Fh -- lightweight filehandle ############### -package Fh; - -use overload - '""' => \&asString, - 'cmp' => \&compare, - 'fallback'=>1; - -$FH='fh00000'; - -*Fh::AUTOLOAD = \&CGI::AUTOLOAD; - -sub DESTROY { - my $self = shift; - close $self; -} - -$AUTOLOADED_ROUTINES = ''; # prevent -w error -$AUTOLOADED_ROUTINES=<<'END_OF_AUTOLOAD'; -%SUBS = ( -'asString' => <<'END_OF_FUNC', -sub asString { - my $self = shift; - # get rid of package name - (my $i = $$self) =~ s/^\*(\w+::fh\d{5})+//; - $i =~ s/%(..)/ chr(hex($1)) /eg; - return $i.$CGI::TAINTED; -# BEGIN DEAD CODE -# This was an extremely clever patch that allowed "use strict refs". -# Unfortunately it relied on another bug that caused leaky file descriptors. -# The underlying bug has been fixed, so this no longer works. However -# "strict refs" still works for some reason. -# my $self = shift; -# return ${*{$self}{SCALAR}}; -# END DEAD CODE -} -END_OF_FUNC - -'compare' => <<'END_OF_FUNC', -sub compare { - my $self = shift; - my $value = shift; - return "$self" cmp $value; -} -END_OF_FUNC - -'new' => <<'END_OF_FUNC', -sub new { - my($pack,$name,$file,$delete) = @_; - _setup_symbols(@SAVED_SYMBOLS) if @SAVED_SYMBOLS; - require Fcntl unless defined &Fcntl::O_RDWR; - (my $safename = $name) =~ s/([':%])/ sprintf '%%%02X', ord $1 /eg; - my $fv = ++$FH . $safename; - my $ref = \*{"Fh::$fv"}; - - # Note this same regex is also used elsewhere in the same file for CGITempFile::new - $file =~ m!^([a-zA-Z0-9_ \'\":/.\$\\\+-]+)$! || return; - my $safe = $1; - sysopen($ref,$safe,Fcntl::O_RDWR()|Fcntl::O_CREAT()|Fcntl::O_EXCL(),0600) || return; - unlink($safe) if $delete; - CORE::delete $Fh::{$fv}; - return bless $ref,$pack; -} -END_OF_FUNC - -'handle' => <<'END_OF_FUNC', -sub handle { - my $self = shift; - eval "require IO::Handle" unless IO::Handle->can('new_from_fd'); - return IO::Handle->new_from_fd(fileno $self,"<"); -} -END_OF_FUNC - -); -END_OF_AUTOLOAD - -######################## MultipartBuffer #################### -package MultipartBuffer; - -use constant DEBUG => 0; - -# how many bytes to read at a time. We use -# a 4K buffer by default. -$INITIAL_FILLUNIT = 1024 * 4; -$TIMEOUT = 240*60; # 4 hour timeout for big files -$SPIN_LOOP_MAX = 2000; # bug fix for some Netscape servers -$CRLF=$CGI::CRLF; - -#reuse the autoload function -*MultipartBuffer::AUTOLOAD = \&CGI::AUTOLOAD; - -# avoid autoloader warnings -sub DESTROY {} - -############################################################################### -################# THESE FUNCTIONS ARE AUTOLOADED ON DEMAND #################### -############################################################################### -$AUTOLOADED_ROUTINES = ''; # prevent -w error -$AUTOLOADED_ROUTINES=<<'END_OF_AUTOLOAD'; -%SUBS = ( - -'new' => <<'END_OF_FUNC', -sub new { - my($package,$interface,$boundary,$length) = @_; - $FILLUNIT = $INITIAL_FILLUNIT; - $CGI::DefaultClass->binmode($IN); # if $CGI::needs_binmode; # just do it always - - # If the user types garbage into the file upload field, - # then Netscape passes NOTHING to the server (not good). - # We may hang on this read in that case. So we implement - # a read timeout. If nothing is ready to read - # by then, we return. - - # Netscape seems to be a little bit unreliable - # about providing boundary strings. - my $boundary_read = 0; - if ($boundary) { - - # Under the MIME spec, the boundary consists of the - # characters "--" PLUS the Boundary string - - # BUG: IE 3.01 on the Macintosh uses just the boundary -- not - # the two extra hyphens. We do a special case here on the user-agent!!!! - $boundary = "--$boundary" unless CGI::user_agent('MSIE\s+3\.0[12];\s*Mac|DreamPassport'); - - } else { # otherwise we find it ourselves - my($old); - ($old,$/) = ($/,$CRLF); # read a CRLF-delimited line - $boundary = <STDIN>; # BUG: This won't work correctly under mod_perl - $length -= length($boundary); - chomp($boundary); # remove the CRLF - $/ = $old; # restore old line separator - $boundary_read++; - } - - my $self = {LENGTH=>$length, - CHUNKED=>!$length, - BOUNDARY=>$boundary, - INTERFACE=>$interface, - BUFFER=>'', - }; - - $FILLUNIT = length($boundary) - if length($boundary) > $FILLUNIT; - - my $retval = bless $self,ref $package || $package; - - # Read the preamble and the topmost (boundary) line plus the CRLF. - unless ($boundary_read) { - while ($self->read(0)) { } - } - die "Malformed multipart POST: data truncated\n" if $self->eof; - - return $retval; -} -END_OF_FUNC - -'readHeader' => <<'END_OF_FUNC', -sub readHeader { - my($self) = @_; - my($end); - my($ok) = 0; - my($bad) = 0; - - local($CRLF) = "\015\012" if $CGI::OS eq 'VMS' || $CGI::EBCDIC; - - do { - $self->fillBuffer($FILLUNIT); - $ok++ if ($end = index($self->{BUFFER},"${CRLF}${CRLF}")) >= 0; - $ok++ if $self->{BUFFER} eq ''; - $bad++ if !$ok && $self->{LENGTH} <= 0; - # this was a bad idea - # $FILLUNIT *= 2 if length($self->{BUFFER}) >= $FILLUNIT; - } until $ok || $bad; - return () if $bad; - - #EBCDIC NOTE: translate header into EBCDIC, but watch out for continuation lines! - - my($header) = substr($self->{BUFFER},0,$end+2); - substr($self->{BUFFER},0,$end+4) = ''; - my %return; - - if ($CGI::EBCDIC) { - warn "untranslated header=$header\n" if DEBUG; - $header = CGI::Util::ascii2ebcdic($header); - warn "translated header=$header\n" if DEBUG; - } - - # See RFC 2045 Appendix A and RFC 822 sections 3.4.8 - # (Folding Long Header Fields), 3.4.3 (Comments) - # and 3.4.5 (Quoted-Strings). - - my $token = '[-\w!\#$%&\'*+.^_\`|{}~]'; - $header=~s/$CRLF\s+/ /og; # merge continuation lines - - while ($header=~/($token+):\s+([^$CRLF]*)/mgox) { - my ($field_name,$field_value) = ($1,$2); - $field_name =~ s/\b(\w)/uc($1)/eg; #canonicalize - $return{$field_name}=$field_value; - } - return %return; -} -END_OF_FUNC - -# This reads and returns the body as a single scalar value. -'readBody' => <<'END_OF_FUNC', -sub readBody { - my($self) = @_; - my($data); - my($returnval)=''; - - #EBCDIC NOTE: want to translate returnval into EBCDIC HERE - - while (defined($data = $self->read)) { - $returnval .= $data; - } - - if ($CGI::EBCDIC) { - warn "untranslated body=$returnval\n" if DEBUG; - $returnval = CGI::Util::ascii2ebcdic($returnval); - warn "translated body=$returnval\n" if DEBUG; - } - return $returnval; -} -END_OF_FUNC - -# This will read $bytes or until the boundary is hit, whichever happens -# first. After the boundary is hit, we return undef. The next read will -# skip over the boundary and begin reading again; -'read' => <<'END_OF_FUNC', -sub read { - my($self,$bytes) = @_; - - # default number of bytes to read - $bytes = $bytes || $FILLUNIT; - - # Fill up our internal buffer in such a way that the boundary - # is never split between reads. - $self->fillBuffer($bytes); - - my $boundary_start = $CGI::EBCDIC ? CGI::Util::ebcdic2ascii($self->{BOUNDARY}) : $self->{BOUNDARY}; - my $boundary_end = $CGI::EBCDIC ? CGI::Util::ebcdic2ascii($self->{BOUNDARY}.'--') : $self->{BOUNDARY}.'--'; - - # Find the boundary in the buffer (it may not be there). - my $start = index($self->{BUFFER},$boundary_start); - - warn "boundary=$self->{BOUNDARY} length=$self->{LENGTH} start=$start\n" if DEBUG; - - # protect against malformed multipart POST operations - die "Malformed multipart POST\n" unless $self->{CHUNKED} || ($start >= 0 || $self->{LENGTH} > 0); - - #EBCDIC NOTE: want to translate boundary search into ASCII here. - - # If the boundary begins the data, then skip past it - # and return undef. - if ($start == 0) { - - # clear us out completely if we've hit the last boundary. - if (index($self->{BUFFER},$boundary_end)==0) { - $self->{BUFFER}=''; - $self->{LENGTH}=0; - return undef; - } - - # just remove the boundary. - substr($self->{BUFFER},0,length($boundary_start))=''; - $self->{BUFFER} =~ s/^\012\015?//; - return undef; - } - - my $bytesToReturn; - if ($start > 0) { # read up to the boundary - $bytesToReturn = $start-2 > $bytes ? $bytes : $start; - } else { # read the requested number of bytes - # leave enough bytes in the buffer to allow us to read - # the boundary. Thanks to Kevin Hendrick for finding - # this one. - $bytesToReturn = $bytes - (length($boundary_start)+1); - } - - my $returnval=substr($self->{BUFFER},0,$bytesToReturn); - substr($self->{BUFFER},0,$bytesToReturn)=''; - - # If we hit the boundary, remove the CRLF from the end. - return ($bytesToReturn==$start) - ? substr($returnval,0,-2) : $returnval; -} -END_OF_FUNC - - -# This fills up our internal buffer in such a way that the -# boundary is never split between reads -'fillBuffer' => <<'END_OF_FUNC', -sub fillBuffer { - my($self,$bytes) = @_; - return unless $self->{CHUNKED} || $self->{LENGTH}; - - my($boundaryLength) = length($self->{BOUNDARY}); - my($bufferLength) = length($self->{BUFFER}); - my($bytesToRead) = $bytes - $bufferLength + $boundaryLength + 2; - $bytesToRead = $self->{LENGTH} if !$self->{CHUNKED} && $self->{LENGTH} < $bytesToRead; - - # Try to read some data. We may hang here if the browser is screwed up. - my $bytesRead = $self->{INTERFACE}->read_from_client(\$self->{BUFFER}, - $bytesToRead, - $bufferLength); - warn "bytesToRead=$bytesToRead, bufferLength=$bufferLength, buffer=$self->{BUFFER}\n" if DEBUG; - $self->{BUFFER} = '' unless defined $self->{BUFFER}; - - # An apparent bug in the Apache server causes the read() - # to return zero bytes repeatedly without blocking if the - # remote user aborts during a file transfer. I don't know how - # they manage this, but the workaround is to abort if we get - # more than SPIN_LOOP_MAX consecutive zero reads. - if ($bytesRead <= 0) { - die "CGI.pm: Server closed socket during multipart read (client aborted?).\n" - if ($self->{ZERO_LOOP_COUNTER}++ >= $SPIN_LOOP_MAX); - } else { - $self->{ZERO_LOOP_COUNTER}=0; - } - - $self->{LENGTH} -= $bytesRead if !$self->{CHUNKED} && $bytesRead; -} -END_OF_FUNC - - -# Return true when we've finished reading -'eof' => <<'END_OF_FUNC' -sub eof { - my($self) = @_; - return 1 if (length($self->{BUFFER}) == 0) - && ($self->{LENGTH} <= 0); - undef; -} -END_OF_FUNC - -); -END_OF_AUTOLOAD - -#################################################################################### -################################## TEMPORARY FILES ################################# -#################################################################################### -package CGITempFile; - -sub find_tempdir { - $SL = $CGI::SL; - $MAC = $CGI::OS eq 'MACINTOSH'; - my ($vol) = $MAC ? MacPerl::Volumes() =~ /:(.*)/ : ""; - unless (defined $TMPDIRECTORY) { - @TEMP=("${SL}usr${SL}tmp","${SL}var${SL}tmp", - "C:${SL}temp","${SL}tmp","${SL}temp", - "${vol}${SL}Temporary Items", - "${SL}WWW_ROOT", "${SL}SYS\$SCRATCH", - "C:${SL}system${SL}temp"); - - if( $CGI::OS eq 'WINDOWS' ){ - # PeterH: These evars may not exist if this is invoked within a service and untainting - # is in effect - with 'use warnings' the undefined array entries causes Perl to die - unshift(@TEMP,$ENV{TEMP}) if defined $ENV{TEMP}; - unshift(@TEMP,$ENV{TMP}) if defined $ENV{TMP}; - unshift(@TEMP,$ENV{WINDIR} . $SL . 'TEMP') if defined $ENV{WINDIR}; - } - - unshift(@TEMP,$ENV{'TMPDIR'}) if defined $ENV{'TMPDIR'}; - - # this feature was supposed to provide per-user tmpfiles, but - # it is problematic. - # unshift(@TEMP,(getpwuid($<))[7].'/tmp') if $CGI::OS eq 'UNIX'; - # Rob: getpwuid() is unfortunately UNIX specific. On brain dead OS'es this - # : can generate a 'getpwuid() not implemented' exception, even though - # : it's never called. Found under DOS/Win with the DJGPP perl port. - # : Refer to getpwuid() only at run-time if we're fortunate and have UNIX. - # unshift(@TEMP,(eval {(getpwuid($>))[7]}).'/tmp') if $CGI::OS eq 'UNIX' and $> != 0; - - for (@TEMP) { - do {$TMPDIRECTORY = $_; last} if -d $_ && -w _; - } - } - $TMPDIRECTORY = $MAC ? "" : "." unless $TMPDIRECTORY; -} - -find_tempdir(); - -$MAXTRIES = 5000; - -# cute feature, but overload implementation broke it -# %OVERLOAD = ('""'=>'as_string'); -*CGITempFile::AUTOLOAD = \&CGI::AUTOLOAD; - -sub DESTROY { - my($self) = @_; - $$self =~ m!^([a-zA-Z0-9_ \'\":/.\$\\~-]+)$! || return; - my $safe = $1; # untaint operation - unlink $safe; # get rid of the file -} - -############################################################################### -################# THESE FUNCTIONS ARE AUTOLOADED ON DEMAND #################### -############################################################################### -$AUTOLOADED_ROUTINES = ''; # prevent -w error -$AUTOLOADED_ROUTINES=<<'END_OF_AUTOLOAD'; -%SUBS = ( - -'new' => <<'END_OF_FUNC', -sub new { - my($package,$sequence) = @_; - my $filename; - find_tempdir() unless -w $TMPDIRECTORY; - for (my $i = 0; $i < $MAXTRIES; $i++) { - last if ! -f ($filename = sprintf("\%s${SL}CGItemp%d", $TMPDIRECTORY, $sequence++)); - } - # check that it is a more-or-less valid filename - # Note this same regex is also used elsewhere in the same file for Fh::new - return unless $filename =~ m!^([a-zA-Z0-9_ \'\":/.\$\\\+-]+)$!; - # this used to untaint, now it doesn't - # $filename = $1; - return bless \$filename; -} -END_OF_FUNC - -'as_string' => <<'END_OF_FUNC' -sub as_string { - my($self) = @_; - return $$self; -} -END_OF_FUNC - -); -END_OF_AUTOLOAD - -package CGI; - -# We get a whole bunch of warnings about "possibly uninitialized variables" -# when running with the -w switch. Touch them all once to get rid of the -# warnings. This is ugly and I hate it. -if ($^W) { - $CGI::CGI = ''; - $CGI::CGI=<<EOF; - $CGI::VERSION; - $MultipartBuffer::SPIN_LOOP_MAX; - $MultipartBuffer::CRLF; - $MultipartBuffer::TIMEOUT; - $MultipartBuffer::INITIAL_FILLUNIT; -EOF - ; -} - -1; - -__END__ - -=head1 NAME - -CGI - Handle Common Gateway Interface requests and responses - -=head1 SYNOPSIS - - use CGI; - - my $q = CGI->new; - - # Process an HTTP request - @values = $q->param('form_field'); - - $fh = $q->upload('file_field'); - - $riddle = $query->cookie('riddle_name'); - %answers = $query->cookie('answers'); - - # Prepare various HTTP responses - print $q->header(); - print $q->header('application/json'); - - $cookie1 = $q->cookie(-name=>'riddle_name', -value=>"The Sphynx's Question"); - $cookie2 = $q->cookie(-name=>'answers', -value=>\%answers); - print $q->header( - -type => 'image/gif', - -expires => '+3d', - -cookie => [$cookie1,$cookie2] - ); - - print $q->redirect('http://somewhere.else/in/movie/land'); - -=head1 DESCRIPTION - -CGI.pm is a stable, complete and mature solution for processing and preparing -HTTP requests and responses. Major features including processing form -submissions, file uploads, reading and writing cookies, query string generation -and manipulation, and processing and preparing HTTP headers. Some HTML -generation utilities are included as well. - -CGI.pm performs very well in in a vanilla CGI.pm environment and also comes -with built-in support for mod_perl and mod_perl2 as well as FastCGI. - -It has the benefit of having developed and refined over 10 years with input -from dozens of contributors and being deployed on thousands of websites. -CGI.pm has been included in the Perl distribution since Perl 5.4, and has -become a de-facto standard. - -=head2 PROGRAMMING STYLE - -There are two styles of programming with CGI.pm, an object-oriented -style and a function-oriented style. In the object-oriented style you -create one or more CGI objects and then use object methods to create -the various elements of the page. Each CGI object starts out with the -list of named parameters that were passed to your CGI script by the -server. You can modify the objects, save them to a file or database -and recreate them. Because each object corresponds to the "state" of -the CGI script, and because each object's parameter list is -independent of the others, this allows you to save the state of the -script and restore it later. - -For example, using the object oriented style, here is how you create -a simple "Hello World" HTML page: - - #!/usr/local/bin/perl -w - use CGI; # load CGI routines - $q = new CGI; # create new CGI object - print $q->header, # create the HTTP header - $q->start_html('hello world'), # start the HTML - $q->h1('hello world'), # level 1 header - $q->end_html; # end the HTML - -In the function-oriented style, there is one default CGI object that -you rarely deal with directly. Instead you just call functions to -retrieve CGI parameters, create HTML tags, manage cookies, and so -on. This provides you with a cleaner programming interface, but -limits you to using one CGI object at a time. The following example -prints the same page, but uses the function-oriented interface. -The main differences are that we now need to import a set of functions -into our name space (usually the "standard" functions), and we don't -need to create the CGI object. - - #!/usr/local/bin/perl - use CGI qw/:standard/; # load standard CGI routines - print header, # create the HTTP header - start_html('hello world'), # start the HTML - h1('hello world'), # level 1 header - end_html; # end the HTML - -The examples in this document mainly use the object-oriented style. -See HOW TO IMPORT FUNCTIONS for important information on -function-oriented programming in CGI.pm - -=head2 CALLING CGI.PM ROUTINES - -Most CGI.pm routines accept several arguments, sometimes as many as 20 -optional ones! To simplify this interface, all routines use a named -argument calling style that looks like this: - - print $q->header(-type=>'image/gif',-expires=>'+3d'); - -Each argument name is preceded by a dash. Neither case nor order -matters in the argument list. -type, -Type, and -TYPE are all -acceptable. In fact, only the first argument needs to begin with a -dash. If a dash is present in the first argument, CGI.pm assumes -dashes for the subsequent ones. - -Several routines are commonly called with just one argument. In the -case of these routines you can provide the single argument without an -argument name. header() happens to be one of these routines. In this -case, the single argument is the document type. - - print $q->header('text/html'); - -Other such routines are documented below. - -Sometimes named arguments expect a scalar, sometimes a reference to an -array, and sometimes a reference to a hash. Often, you can pass any -type of argument and the routine will do whatever is most appropriate. -For example, the param() routine is used to set a CGI parameter to a -single or a multi-valued value. The two cases are shown below: - - $q->param(-name=>'veggie',-value=>'tomato'); - $q->param(-name=>'veggie',-value=>['tomato','tomahto','potato','potahto']); - -A large number of routines in CGI.pm actually aren't specifically -defined in the module, but are generated automatically as needed. -These are the "HTML shortcuts," routines that generate HTML tags for -use in dynamically-generated pages. HTML tags have both attributes -(the attribute="value" pairs within the tag itself) and contents (the -part between the opening and closing pairs.) To distinguish between -attributes and contents, CGI.pm uses the convention of passing HTML -attributes as a hash reference as the first argument, and the -contents, if any, as any subsequent arguments. It works out like -this: - - Code Generated HTML - ---- -------------- - h1() <h1> - h1('some','contents'); <h1>some contents</h1> - h1({-align=>left}); <h1 align="LEFT"> - h1({-align=>left},'contents'); <h1 align="LEFT">contents</h1> - -HTML tags are described in more detail later. - -Many newcomers to CGI.pm are puzzled by the difference between the -calling conventions for the HTML shortcuts, which require curly braces -around the HTML tag attributes, and the calling conventions for other -routines, which manage to generate attributes without the curly -brackets. Don't be confused. As a convenience the curly braces are -optional in all but the HTML shortcuts. If you like, you can use -curly braces when calling any routine that takes named arguments. For -example: - - print $q->header( {-type=>'image/gif',-expires=>'+3d'} ); - -If you use the B<-w> switch, you will be warned that some CGI.pm argument -names conflict with built-in Perl functions. The most frequent of -these is the -values argument, used to create multi-valued menus, -radio button clusters and the like. To get around this warning, you -have several choices: - -=over 4 - -=item 1. - -Use another name for the argument, if one is available. -For example, -value is an alias for -values. - -=item 2. - -Change the capitalization, e.g. -Values - -=item 3. - -Put quotes around the argument name, e.g. '-values' - -=back - -Many routines will do something useful with a named argument that it -doesn't recognize. For example, you can produce non-standard HTTP -header fields by providing them as named arguments: - - print $q->header(-type => 'text/html', - -cost => 'Three smackers', - -annoyance_level => 'high', - -complaints_to => 'bit bucket'); - -This will produce the following nonstandard HTTP header: - - HTTP/1.0 200 OK - Cost: Three smackers - Annoyance-level: high - Complaints-to: bit bucket - Content-type: text/html - -Notice the way that underscores are translated automatically into -hyphens. HTML-generating routines perform a different type of -translation. - -This feature allows you to keep up with the rapidly changing HTTP and -HTML "standards". - -=head2 CREATING A NEW QUERY OBJECT (OBJECT-ORIENTED STYLE): - - $query = new CGI; - -This will parse the input (from both POST and GET methods) and store -it into a perl5 object called $query. - -Any filehandles from file uploads will have their position reset to -the beginning of the file. - -=head2 CREATING A NEW QUERY OBJECT FROM AN INPUT FILE - - $query = new CGI(INPUTFILE); - -If you provide a file handle to the new() method, it will read -parameters from the file (or STDIN, or whatever). The file can be in -any of the forms describing below under debugging (i.e. a series of -newline delimited TAG=VALUE pairs will work). Conveniently, this type -of file is created by the save() method (see below). Multiple records -can be saved and restored. - -Perl purists will be pleased to know that this syntax accepts -references to file handles, or even references to filehandle globs, -which is the "official" way to pass a filehandle: - - $query = new CGI(\*STDIN); - -You can also initialize the CGI object with a FileHandle or IO::File -object. - -If you are using the function-oriented interface and want to -initialize CGI state from a file handle, the way to do this is with -B<restore_parameters()>. This will (re)initialize the -default CGI object from the indicated file handle. - - open (IN,"test.in") || die; - restore_parameters(IN); - close IN; - -You can also initialize the query object from a hash -reference: - - $query = new CGI( {'dinosaur'=>'barney', - 'song'=>'I love you', - 'friends'=>[qw/Jessica George Nancy/]} - ); - -or from a properly formatted, URL-escaped query string: - - $query = new CGI('dinosaur=barney&color=purple'); - -or from a previously existing CGI object (currently this clones the -parameter list, but none of the other object-specific fields, such as -autoescaping): - - $old_query = new CGI; - $new_query = new CGI($old_query); - -To create an empty query, initialize it from an empty string or hash: - - $empty_query = new CGI(""); - - -or- - - $empty_query = new CGI({}); - -=head2 FETCHING A LIST OF KEYWORDS FROM THE QUERY: - - @keywords = $query->keywords - -If the script was invoked as the result of an <ISINDEX> search, the -parsed keywords can be obtained as an array using the keywords() method. - -=head2 FETCHING THE NAMES OF ALL THE PARAMETERS PASSED TO YOUR SCRIPT: - - @names = $query->param - -If the script was invoked with a parameter list -(e.g. "name1=value1&name2=value2&name3=value3"), the param() method -will return the parameter names as a list. If the script was invoked -as an <ISINDEX> script and contains a string without ampersands -(e.g. "value1+value2+value3") , there will be a single parameter named -"keywords" containing the "+"-delimited keywords. - -NOTE: As of version 1.5, the array of parameter names returned will -be in the same order as they were submitted by the browser. -Usually this order is the same as the order in which the -parameters are defined in the form (however, this isn't part -of the spec, and so isn't guaranteed). - -=head2 FETCHING THE VALUE OR VALUES OF A SINGLE NAMED PARAMETER: - - @values = $query->param('foo'); - - -or- - - $value = $query->param('foo'); - -Pass the param() method a single argument to fetch the value of the -named parameter. If the parameter is multivalued (e.g. from multiple -selections in a scrolling list), you can ask to receive an array. Otherwise -the method will return a single value. - -If a value is not given in the query string, as in the queries -"name1=&name2=", it will be returned as an empty string. - - -If the parameter does not exist at all, then param() will return undef -in a scalar context, and the empty list in a list context. - - -=head2 SETTING THE VALUE(S) OF A NAMED PARAMETER: - - $query->param('foo','an','array','of','values'); - -This sets the value for the named parameter 'foo' to an array of -values. This is one way to change the value of a field AFTER -the script has been invoked once before. (Another way is with -the -override parameter accepted by all methods that generate -form elements.) - -param() also recognizes a named parameter style of calling described -in more detail later: - - $query->param(-name=>'foo',-values=>['an','array','of','values']); - - -or- - - $query->param(-name=>'foo',-value=>'the value'); - -=head2 APPENDING ADDITIONAL VALUES TO A NAMED PARAMETER: - - $query->append(-name=>'foo',-values=>['yet','more','values']); - -This adds a value or list of values to the named parameter. The -values are appended to the end of the parameter if it already exists. -Otherwise the parameter is created. Note that this method only -recognizes the named argument calling syntax. - -=head2 IMPORTING ALL PARAMETERS INTO A NAMESPACE: - - $query->import_names('R'); - -This creates a series of variables in the 'R' namespace. For example, -$R::foo, @R:foo. For keyword lists, a variable @R::keywords will appear. -If no namespace is given, this method will assume 'Q'. -WARNING: don't import anything into 'main'; this is a major security -risk!!!! - -NOTE 1: Variable names are transformed as necessary into legal Perl -variable names. All non-legal characters are transformed into -underscores. If you need to keep the original names, you should use -the param() method instead to access CGI variables by name. - -NOTE 2: In older versions, this method was called B<import()>. As of version 2.20, -this name has been removed completely to avoid conflict with the built-in -Perl module B<import> operator. - -=head2 DELETING A PARAMETER COMPLETELY: - - $query->delete('foo','bar','baz'); - -This completely clears a list of parameters. It sometimes useful for -resetting parameters that you don't want passed down between script -invocations. - -If you are using the function call interface, use "Delete()" instead -to avoid conflicts with Perl's built-in delete operator. - -=head2 DELETING ALL PARAMETERS: - - $query->delete_all(); - -This clears the CGI object completely. It might be useful to ensure -that all the defaults are taken when you create a fill-out form. - -Use Delete_all() instead if you are using the function call interface. - -=head2 HANDLING NON-URLENCODED ARGUMENTS - - -If POSTed data is not of type application/x-www-form-urlencoded or -multipart/form-data, then the POSTed data will not be processed, but -instead be returned as-is in a parameter named POSTDATA. To retrieve -it, use code like this: - - my $data = $query->param('POSTDATA'); - -Likewise if PUTed data can be retrieved with code like this: - - my $data = $query->param('PUTDATA'); - -(If you don't know what the preceding means, don't worry about it. It -only affects people trying to use CGI for XML processing and other -specialized tasks.) - - -=head2 DIRECT ACCESS TO THE PARAMETER LIST: - - $q->param_fetch('address')->[1] = '1313 Mockingbird Lane'; - unshift @{$q->param_fetch(-name=>'address')},'George Munster'; - -If you need access to the parameter list in a way that isn't covered -by the methods above, you can obtain a direct reference to it by -calling the B<param_fetch()> method with the name of the . This -will return an array reference to the named parameters, which you then -can manipulate in any way you like. - -You can also use a named argument style using the B<-name> argument. - -=head2 FETCHING THE PARAMETER LIST AS A HASH: - - $params = $q->Vars; - print $params->{'address'}; - @foo = split("\0",$params->{'foo'}); - %params = $q->Vars; - - use CGI ':cgi-lib'; - $params = Vars; - -Many people want to fetch the entire parameter list as a hash in which -the keys are the names of the CGI parameters, and the values are the -parameters' values. The Vars() method does this. Called in a scalar -context, it returns the parameter list as a tied hash reference. -Changing a key changes the value of the parameter in the underlying -CGI parameter list. Called in a list context, it returns the -parameter list as an ordinary hash. This allows you to read the -contents of the parameter list, but not to change it. - -When using this, the thing you must watch out for are multivalued CGI -parameters. Because a hash cannot distinguish between scalar and -list context, multivalued parameters will be returned as a packed -string, separated by the "\0" (null) character. You must split this -packed string in order to get at the individual values. This is the -convention introduced long ago by Steve Brenner in his cgi-lib.pl -module for Perl version 4. - -If you wish to use Vars() as a function, import the I<:cgi-lib> set of -function calls (also see the section on CGI-LIB compatibility). - -=head2 SAVING THE STATE OF THE SCRIPT TO A FILE: - - $query->save(\*FILEHANDLE) - -This will write the current state of the form to the provided -filehandle. You can read it back in by providing a filehandle -to the new() method. Note that the filehandle can be a file, a pipe, -or whatever! - -The format of the saved file is: - - NAME1=VALUE1 - NAME1=VALUE1' - NAME2=VALUE2 - NAME3=VALUE3 - = - -Both name and value are URL escaped. Multi-valued CGI parameters are -represented as repeated names. A session record is delimited by a -single = symbol. You can write out multiple records and read them -back in with several calls to B<new>. You can do this across several -sessions by opening the file in append mode, allowing you to create -primitive guest books, or to keep a history of users' queries. Here's -a short example of creating multiple session records: - - use CGI; - - open (OUT,">>test.out") || die; - $records = 5; - for (0..$records) { - my $q = new CGI; - $q->param(-name=>'counter',-value=>$_); - $q->save(\*OUT); - } - close OUT; - - # reopen for reading - open (IN,"test.out") || die; - while (!eof(IN)) { - my $q = new CGI(\*IN); - print $q->param('counter'),"\n"; - } - -The file format used for save/restore is identical to that used by the -Whitehead Genome Center's data exchange format "Boulderio", and can be -manipulated and even databased using Boulderio utilities. See - - http://stein.cshl.org/boulder/ - -for further details. - -If you wish to use this method from the function-oriented (non-OO) -interface, the exported name for this method is B<save_parameters()>. - -=head2 RETRIEVING CGI ERRORS - -Errors can occur while processing user input, particularly when -processing uploaded files. When these errors occur, CGI will stop -processing and return an empty parameter list. You can test for -the existence and nature of errors using the I<cgi_error()> function. -The error messages are formatted as HTTP status codes. You can either -incorporate the error text into an HTML page, or use it as the value -of the HTTP status: - - my $error = $q->cgi_error; - if ($error) { - print $q->header(-status=>$error), - $q->start_html('Problems'), - $q->h2('Request not processed'), - $q->strong($error); - exit 0; - } - -When using the function-oriented interface (see the next section), -errors may only occur the first time you call I<param()>. Be ready -for this! - -=head2 USING THE FUNCTION-ORIENTED INTERFACE - -To use the function-oriented interface, you must specify which CGI.pm -routines or sets of routines to import into your script's namespace. -There is a small overhead associated with this importation, but it -isn't much. - - use CGI <list of methods>; - -The listed methods will be imported into the current package; you can -call them directly without creating a CGI object first. This example -shows how to import the B<param()> and B<header()> -methods, and then use them directly: - - use CGI 'param','header'; - print header('text/plain'); - $zipcode = param('zipcode'); - -More frequently, you'll import common sets of functions by referring -to the groups by name. All function sets are preceded with a ":" -character as in ":html3" (for tags defined in the HTML 3 standard). - -Here is a list of the function sets you can import: - -=over 4 - -=item B<:cgi> - -Import all CGI-handling methods, such as B<param()>, B<path_info()> -and the like. - -=item B<:form> - -Import all fill-out form generating methods, such as B<textfield()>. - -=item B<:html2> - -Import all methods that generate HTML 2.0 standard elements. - -=item B<:html3> - -Import all methods that generate HTML 3.0 elements (such as -<table>, <super> and <sub>). - -=item B<:html4> - -Import all methods that generate HTML 4 elements (such as -<abbrev>, <acronym> and <thead>). - -=item B<:netscape> - -Import all methods that generate Netscape-specific HTML extensions. - -=item B<:html> - -Import all HTML-generating shortcuts (i.e. 'html2' + 'html3' + -'netscape')... - -=item B<:standard> - -Import "standard" features, 'html2', 'html3', 'html4', 'form' and 'cgi'. - -=item B<:all> - -Import all the available methods. For the full list, see the CGI.pm -code, where the variable %EXPORT_TAGS is defined. - -=back - -If you import a function name that is not part of CGI.pm, the module -will treat it as a new HTML tag and generate the appropriate -subroutine. You can then use it like any other HTML tag. This is to -provide for the rapidly-evolving HTML "standard." For example, say -Microsoft comes out with a new tag called <gradient> (which causes the -user's desktop to be flooded with a rotating gradient fill until his -machine reboots). You don't need to wait for a new version of CGI.pm -to start using it immediately: - - use CGI qw/:standard :html3 gradient/; - print gradient({-start=>'red',-end=>'blue'}); - -Note that in the interests of execution speed CGI.pm does B<not> use -the standard L<Exporter> syntax for specifying load symbols. This may -change in the future. - -If you import any of the state-maintaining CGI or form-generating -methods, a default CGI object will be created and initialized -automatically the first time you use any of the methods that require -one to be present. This includes B<param()>, B<textfield()>, -B<submit()> and the like. (If you need direct access to the CGI -object, you can find it in the global variable B<$CGI::Q>). By -importing CGI.pm methods, you can create visually elegant scripts: - - use CGI qw/:standard/; - print - header, - start_html('Simple Script'), - h1('Simple Script'), - start_form, - "What's your name? ",textfield('name'),p, - "What's the combination?", - checkbox_group(-name=>'words', - -values=>['eenie','meenie','minie','moe'], - -defaults=>['eenie','moe']),p, - "What's your favorite color?", - popup_menu(-name=>'color', - -values=>['red','green','blue','chartreuse']),p, - submit, - end_form, - hr,"\n"; - - if (param) { - print - "Your name is ",em(param('name')),p, - "The keywords are: ",em(join(", ",param('words'))),p, - "Your favorite color is ",em(param('color')),".\n"; - } - print end_html; - -=head2 PRAGMAS - -In addition to the function sets, there are a number of pragmas that -you can import. Pragmas, which are always preceded by a hyphen, -change the way that CGI.pm functions in various ways. Pragmas, -function sets, and individual functions can all be imported in the -same use() line. For example, the following use statement imports the -standard set of functions and enables debugging mode (pragma --debug): - - use CGI qw/:standard -debug/; - -The current list of pragmas is as follows: - -=over 4 - -=item -any - -When you I<use CGI -any>, then any method that the query object -doesn't recognize will be interpreted as a new HTML tag. This allows -you to support the next I<ad hoc> Netscape or Microsoft HTML -extension. This lets you go wild with new and unsupported tags: - - use CGI qw(-any); - $q=new CGI; - print $q->gradient({speed=>'fast',start=>'red',end=>'blue'}); - -Since using <cite>any</cite> causes any mistyped method name -to be interpreted as an HTML tag, use it with care or not at -all. - -=item -compile - -This causes the indicated autoloaded methods to be compiled up front, -rather than deferred to later. This is useful for scripts that run -for an extended period of time under FastCGI or mod_perl, and for -those destined to be crunched by Malcolm Beattie's Perl compiler. Use -it in conjunction with the methods or method families you plan to use. - - use CGI qw(-compile :standard :html3); - -or even - - use CGI qw(-compile :all); - -Note that using the -compile pragma in this way will always have -the effect of importing the compiled functions into the current -namespace. If you want to compile without importing use the -compile() method instead: - - use CGI(); - CGI->compile(); - -This is particularly useful in a mod_perl environment, in which you -might want to precompile all CGI routines in a startup script, and -then import the functions individually in each mod_perl script. - -=item -nosticky - -By default the CGI module implements a state-preserving behavior -called "sticky" fields. The way this works is that if you are -regenerating a form, the methods that generate the form field values -will interrogate param() to see if similarly-named parameters are -present in the query string. If they find a like-named parameter, they -will use it to set their default values. - -Sometimes this isn't what you want. The B<-nosticky> pragma prevents -this behavior. You can also selectively change the sticky behavior in -each element that you generate. - -=item -tabindex - -Automatically add tab index attributes to each form field. With this -option turned off, you can still add tab indexes manually by passing a --tabindex option to each field-generating method. - -=item -no_undef_params - -This keeps CGI.pm from including undef params in the parameter list. - -=item -no_xhtml - -By default, CGI.pm versions 2.69 and higher emit XHTML -(http://www.w3.org/TR/xhtml1/). The -no_xhtml pragma disables this -feature. Thanks to Michalis Kabrianis <kabrianis@hellug.gr> for this -feature. - -If start_html()'s -dtd parameter specifies an HTML 2.0 or 3.2 DTD, -XHTML will automatically be disabled without needing to use this -pragma. - -=item -utf8 - -This makes CGI.pm treat all parameters as UTF-8 strings. Use this with -care, as it will interfere with the processing of binary uploads. It -is better to manually select which fields are expected to return utf-8 -strings and convert them using code like this: - - use Encode; - my $arg = decode utf8=>param('foo'); - -=item -nph - -This makes CGI.pm produce a header appropriate for an NPH (no -parsed header) script. You may need to do other things as well -to tell the server that the script is NPH. See the discussion -of NPH scripts below. - -=item -newstyle_urls - -Separate the name=value pairs in CGI parameter query strings with -semicolons rather than ampersands. For example: - - ?name=fred;age=24;favorite_color=3 - -Semicolon-delimited query strings are always accepted, but will not be -emitted by self_url() and query_string() unless the -newstyle_urls -pragma is specified. - -This became the default in version 2.64. - -=item -oldstyle_urls - -Separate the name=value pairs in CGI parameter query strings with -ampersands rather than semicolons. This is no longer the default. - -=item -autoload - -This overrides the autoloader so that any function in your program -that is not recognized is referred to CGI.pm for possible evaluation. -This allows you to use all the CGI.pm functions without adding them to -your symbol table, which is of concern for mod_perl users who are -worried about memory consumption. I<Warning:> when -I<-autoload> is in effect, you cannot use "poetry mode" -(functions without the parenthesis). Use I<hr()> rather -than I<hr>, or add something like I<use subs qw/hr p header/> -to the top of your script. - -=item -no_debug - -This turns off the command-line processing features. If you want to -run a CGI.pm script from the command line to produce HTML, and you -don't want it to read CGI parameters from the command line or STDIN, -then use this pragma: - - use CGI qw(-no_debug :standard); - -=item -debug - -This turns on full debugging. In addition to reading CGI arguments -from the command-line processing, CGI.pm will pause and try to read -arguments from STDIN, producing the message "(offline mode: enter -name=value pairs on standard input)" features. - -See the section on debugging for more details. - -=item -private_tempfiles - -CGI.pm can process uploaded file. Ordinarily it spools the uploaded -file to a temporary directory, then deletes the file when done. -However, this opens the risk of eavesdropping as described in the file -upload section. Another CGI script author could peek at this data -during the upload, even if it is confidential information. On Unix -systems, the -private_tempfiles pragma will cause the temporary file -to be unlinked as soon as it is opened and before any data is written -into it, reducing, but not eliminating the risk of eavesdropping -(there is still a potential race condition). To make life harder for -the attacker, the program chooses tempfile names by calculating a 32 -bit checksum of the incoming HTTP headers. - -To ensure that the temporary file cannot be read by other CGI scripts, -use suEXEC or a CGI wrapper program to run your script. The temporary -file is created with mode 0600 (neither world nor group readable). - -The temporary directory is selected using the following algorithm: - - 1. if the current user (e.g. "nobody") has a directory named - "tmp" in its home directory, use that (Unix systems only). - - 2. if the environment variable TMPDIR exists, use the location - indicated. - - 3. Otherwise try the locations /usr/tmp, /var/tmp, C:\temp, - /tmp, /temp, ::Temporary Items, and \WWW_ROOT. - -Each of these locations is checked that it is a directory and is -writable. If not, the algorithm tries the next choice. - -=back - -=head2 SPECIAL FORMS FOR IMPORTING HTML-TAG FUNCTIONS - -Many of the methods generate HTML tags. As described below, tag -functions automatically generate both the opening and closing tags. -For example: - - print h1('Level 1 Header'); - -produces - - <h1>Level 1 Header</h1> - -There will be some times when you want to produce the start and end -tags yourself. In this case, you can use the form start_I<tag_name> -and end_I<tag_name>, as in: - - print start_h1,'Level 1 Header',end_h1; - -With a few exceptions (described below), start_I<tag_name> and -end_I<tag_name> functions are not generated automatically when you -I<use CGI>. However, you can specify the tags you want to generate -I<start/end> functions for by putting an asterisk in front of their -name, or, alternatively, requesting either "start_I<tag_name>" or -"end_I<tag_name>" in the import list. - -Example: - - use CGI qw/:standard *table start_ul/; - -In this example, the following functions are generated in addition to -the standard ones: - -=over 4 - -=item 1. start_table() (generates a <table> tag) - -=item 2. end_table() (generates a </table> tag) - -=item 3. start_ul() (generates a <ul> tag) - -=item 4. end_ul() (generates a </ul> tag) - -=back - -=head1 GENERATING DYNAMIC DOCUMENTS - -Most of CGI.pm's functions deal with creating documents on the fly. -Generally you will produce the HTTP header first, followed by the -document itself. CGI.pm provides functions for generating HTTP -headers of various types as well as for generating HTML. For creating -GIF images, see the GD.pm module. - -Each of these functions produces a fragment of HTML or HTTP which you -can print out directly so that it displays in the browser window, -append to a string, or save to a file for later use. - -=head2 CREATING A STANDARD HTTP HEADER: - -Normally the first thing you will do in any CGI script is print out an -HTTP header. This tells the browser what type of document to expect, -and gives other optional information, such as the language, expiration -date, and whether to cache the document. The header can also be -manipulated for special purposes, such as server push and pay per view -pages. - - print header; - - -or- - - print header('image/gif'); - - -or- - - print header('text/html','204 No response'); - - -or- - - print header(-type=>'image/gif', - -nph=>1, - -status=>'402 Payment required', - -expires=>'+3d', - -cookie=>$cookie, - -charset=>'utf-7', - -attachment=>'foo.gif', - -Cost=>'$2.00'); - -header() returns the Content-type: header. You can provide your own -MIME type if you choose, otherwise it defaults to text/html. An -optional second parameter specifies the status code and a human-readable -message. For example, you can specify 204, "No response" to create a -script that tells the browser to do nothing at all. - -The last example shows the named argument style for passing arguments -to the CGI methods using named parameters. Recognized parameters are -B<-type>, B<-status>, B<-expires>, and B<-cookie>. Any other named -parameters will be stripped of their initial hyphens and turned into -header fields, allowing you to specify any HTTP header you desire. -Internal underscores will be turned into hyphens: - - print header(-Content_length=>3002); - -Most browsers will not cache the output from CGI scripts. Every time -the browser reloads the page, the script is invoked anew. You can -change this behavior with the B<-expires> parameter. When you specify -an absolute or relative expiration interval with this parameter, some -browsers and proxy servers will cache the script's output until the -indicated expiration date. The following forms are all valid for the --expires field: - - +30s 30 seconds from now - +10m ten minutes from now - +1h one hour from now - -1d yesterday (i.e. "ASAP!") - now immediately - +3M in three months - +10y in ten years time - Thursday, 25-Apr-1999 00:40:33 GMT at the indicated time & date - -The B<-cookie> parameter generates a header that tells the browser to provide -a "magic cookie" during all subsequent transactions with your script. -Netscape cookies have a special format that includes interesting attributes -such as expiration time. Use the cookie() method to create and retrieve -session cookies. - -The B<-nph> parameter, if set to a true value, will issue the correct -headers to work with a NPH (no-parse-header) script. This is important -to use with certain servers that expect all their scripts to be NPH. - -The B<-charset> parameter can be used to control the character set -sent to the browser. If not provided, defaults to ISO-8859-1. As a -side effect, this sets the charset() method as well. - -The B<-attachment> parameter can be used to turn the page into an -attachment. Instead of displaying the page, some browsers will prompt -the user to save it to disk. The value of the argument is the -suggested name for the saved file. In order for this to work, you may -have to set the B<-type> to "application/octet-stream". - -The B<-p3p> parameter will add a P3P tag to the outgoing header. The -parameter can be an arrayref or a space-delimited string of P3P tags. -For example: - - print header(-p3p=>[qw(CAO DSP LAW CURa)]); - print header(-p3p=>'CAO DSP LAW CURa'); - -In either case, the outgoing header will be formatted as: - - P3P: policyref="/w3c/p3p.xml" cp="CAO DSP LAW CURa" - -=head2 GENERATING A REDIRECTION HEADER - - print $q->redirect('http://somewhere.else/in/movie/land'); - -Sometimes you don't want to produce a document yourself, but simply -redirect the browser elsewhere, perhaps choosing a URL based on the -time of day or the identity of the user. - -The redirect() method redirects the browser to a different URL. If -you use redirection like this, you should B<not> print out a header as -well. - -You should always use full URLs (including the http: or ftp: part) in -redirection requests. Relative URLs will not work correctly. - -You can also use named arguments: - - print $q->redirect( - -uri=>'http://somewhere.else/in/movie/land', - -nph=>1, - -status=>301); - -All names arguments recognized by header() are also recognized by -redirect(). However, most HTTP headers, including those generated by --cookie and -target, are ignored by the browser. - -The B<-nph> parameter, if set to a true value, will issue the correct -headers to work with a NPH (no-parse-header) script. This is important -to use with certain servers, such as Microsoft IIS, which -expect all their scripts to be NPH. - -The B<-status> parameter will set the status of the redirect. HTTP -defines three different possible redirection status codes: - - 301 Moved Permanently - 302 Found - 303 See Other - -The default if not specified is 302, which means "moved temporarily." -You may change the status to another status code if you wish. Be -advised that changing the status to anything other than 301, 302 or -303 will probably break redirection. - -=head2 CREATING THE HTML DOCUMENT HEADER - - print start_html(-title=>'Secrets of the Pyramids', - -author=>'fred@capricorn.org', - -base=>'true', - -target=>'_blank', - -meta=>{'keywords'=>'pharaoh secret mummy', - 'copyright'=>'copyright 1996 King Tut'}, - -style=>{'src'=>'/styles/style1.css'}, - -BGCOLOR=>'blue'); - -After creating the HTTP header, most CGI scripts will start writing -out an HTML document. The start_html() routine creates the top of the -page, along with a lot of optional information that controls the -page's appearance and behavior. - -This method returns a canned HTML header and the opening <body> tag. -All parameters are optional. In the named parameter form, recognized -parameters are -title, -author, -base, -xbase, -dtd, -lang and -target -(see below for the explanation). Any additional parameters you -provide, such as the Netscape unofficial BGCOLOR attribute, are added -to the <body> tag. Additional parameters must be proceeded by a -hyphen. - -The argument B<-xbase> allows you to provide an HREF for the <base> tag -different from the current location, as in - - -xbase=>"http://home.mcom.com/" - -All relative links will be interpreted relative to this tag. - -The argument B<-target> allows you to provide a default target frame -for all the links and fill-out forms on the page. B<This is a -non-standard HTTP feature which only works with Netscape browsers!> -See the Netscape documentation on frames for details of how to -manipulate this. - - -target=>"answer_window" - -All relative links will be interpreted relative to this tag. -You add arbitrary meta information to the header with the B<-meta> -argument. This argument expects a reference to a hash -containing name/value pairs of meta information. These will be turned -into a series of header <meta> tags that look something like this: - - <meta name="keywords" content="pharaoh secret mummy"> - <meta name="description" content="copyright 1996 King Tut"> - -To create an HTTP-EQUIV type of <meta> tag, use B<-head>, described -below. - -The B<-style> argument is used to incorporate cascading stylesheets -into your code. See the section on CASCADING STYLESHEETS for more -information. - -The B<-lang> argument is used to incorporate a language attribute into -the <html> tag. For example: - - print $q->start_html(-lang=>'fr-CA'); - -The default if not specified is "en-US" for US English, unless the --dtd parameter specifies an HTML 2.0 or 3.2 DTD, in which case the -lang attribute is left off. You can force the lang attribute to left -off in other cases by passing an empty string (-lang=>''). - -The B<-encoding> argument can be used to specify the character set for -XHTML. It defaults to iso-8859-1 if not specified. - -The B<-declare_xml> argument, when used in conjunction with XHTML, -will put a <?xml> declaration at the top of the HTML header. The sole -purpose of this declaration is to declare the character set -encoding. In the absence of -declare_xml, the output HTML will contain -a <meta> tag that specifies the encoding, allowing the HTML to pass -most validators. The default for -declare_xml is false. - -You can place other arbitrary HTML elements to the <head> section with the -B<-head> tag. For example, to place the rarely-used <link> element in the -head section, use this: - - print start_html(-head=>Link({-rel=>'next', - -href=>'http://www.capricorn.com/s2.html'})); - -To incorporate multiple HTML elements into the <head> section, just pass an -array reference: - - print start_html(-head=>[ - Link({-rel=>'next', - -href=>'http://www.capricorn.com/s2.html'}), - Link({-rel=>'previous', - -href=>'http://www.capricorn.com/s1.html'}) - ] - ); - -And here's how to create an HTTP-EQUIV <meta> tag: - - print start_html(-head=>meta({-http_equiv => 'Content-Type', - -content => 'text/html'})) - - -JAVASCRIPTING: The B<-script>, B<-noScript>, B<-onLoad>, -B<-onMouseOver>, B<-onMouseOut> and B<-onUnload> parameters are used -to add Netscape JavaScript calls to your pages. B<-script> should -point to a block of text containing JavaScript function definitions. -This block will be placed within a <script> block inside the HTML (not -HTTP) header. The block is placed in the header in order to give your -page a fighting chance of having all its JavaScript functions in place -even if the user presses the stop button before the page has loaded -completely. CGI.pm attempts to format the script in such a way that -JavaScript-naive browsers will not choke on the code: unfortunately -there are some browsers, such as Chimera for Unix, that get confused -by it nevertheless. - -The B<-onLoad> and B<-onUnload> parameters point to fragments of JavaScript -code to execute when the page is respectively opened and closed by the -browser. Usually these parameters are calls to functions defined in the -B<-script> field: - - $query = new CGI; - print header; - $JSCRIPT=<<END; - // Ask a silly question - function riddle_me_this() { - var r = prompt("What walks on four legs in the morning, " + - "two legs in the afternoon, " + - "and three legs in the evening?"); - response(r); - } - // Get a silly answer - function response(answer) { - if (answer == "man") - alert("Right you are!"); - else - alert("Wrong! Guess again."); - } - END - print start_html(-title=>'The Riddle of the Sphinx', - -script=>$JSCRIPT); - -Use the B<-noScript> parameter to pass some HTML text that will be displayed on -browsers that do not have JavaScript (or browsers where JavaScript is turned -off). - -The <script> tag, has several attributes including "type" and src. -The latter is particularly interesting, as it allows you to keep the -JavaScript code in a file or CGI script rather than cluttering up each -page with the source. To use these attributes pass a HASH reference -in the B<-script> parameter containing one or more of -type, -src, or --code: - - print $q->start_html(-title=>'The Riddle of the Sphinx', - -script=>{-type=>'JAVASCRIPT', - -src=>'/javascript/sphinx.js'} - ); - - print $q->(-title=>'The Riddle of the Sphinx', - -script=>{-type=>'PERLSCRIPT', - -code=>'print "hello world!\n;"'} - ); - - -A final feature allows you to incorporate multiple <script> sections into the -header. Just pass the list of script sections as an array reference. -this allows you to specify different source files for different dialects -of JavaScript. Example: - - print $q->start_html(-title=>'The Riddle of the Sphinx', - -script=>[ - { -type => 'text/javascript', - -src => '/javascript/utilities10.js' - }, - { -type => 'text/javascript', - -src => '/javascript/utilities11.js' - }, - { -type => 'text/jscript', - -src => '/javascript/utilities12.js' - }, - { -type => 'text/ecmascript', - -src => '/javascript/utilities219.js' - } - ] - ); - -The option "-language" is a synonym for -type, and is supported for -backwad compatibility. - -The old-style positional parameters are as follows: - -=over 4 - -=item B<Parameters:> - -=item 1. - -The title - -=item 2. - -The author's e-mail address (will create a <link rev="MADE"> tag if present - -=item 3. - -A 'true' flag if you want to include a <base> tag in the header. This -helps resolve relative addresses to absolute ones when the document is moved, -but makes the document hierarchy non-portable. Use with care! - -=item 4, 5, 6... - -Any other parameters you want to include in the <body> tag. This is a good -place to put Netscape extensions, such as colors and wallpaper patterns. - -=back - -=head2 ENDING THE HTML DOCUMENT: - - print end_html - -This ends an HTML document by printing the </body></html> tags. - -=head2 CREATING A SELF-REFERENCING URL THAT PRESERVES STATE INFORMATION: - - $myself = self_url; - print q(<a href="$myself">I'm talking to myself.</a>); - -self_url() will return a URL, that, when selected, will reinvoke -this script with all its state information intact. This is most -useful when you want to jump around within the document using -internal anchors but you don't want to disrupt the current contents -of the form(s). Something like this will do the trick. - - $myself = self_url; - print "<a href=\"$myself#table1\">See table 1</a>"; - print "<a href=\"$myself#table2\">See table 2</a>"; - print "<a href=\"$myself#yourself\">See for yourself</a>"; - -If you want more control over what's returned, using the B<url()> -method instead. - -You can also retrieve the unprocessed query string with query_string(): - - $the_string = query_string; - -=head2 OBTAINING THE SCRIPT'S URL - - $full_url = url(); - $full_url = url(-full=>1); #alternative syntax - $relative_url = url(-relative=>1); - $absolute_url = url(-absolute=>1); - $url_with_path = url(-path_info=>1); - $url_with_path_and_query = url(-path_info=>1,-query=>1); - $netloc = url(-base => 1); - -B<url()> returns the script's URL in a variety of formats. Called -without any arguments, it returns the full form of the URL, including -host name and port number - - http://your.host.com/path/to/script.cgi - -You can modify this format with the following named arguments: - -=over 4 - -=item B<-absolute> - -If true, produce an absolute URL, e.g. - - /path/to/script.cgi - -=item B<-relative> - -Produce a relative URL. This is useful if you want to reinvoke your -script with different parameters. For example: - - script.cgi - -=item B<-full> - -Produce the full URL, exactly as if called without any arguments. -This overrides the -relative and -absolute arguments. - -=item B<-path> (B<-path_info>) - -Append the additional path information to the URL. This can be -combined with B<-full>, B<-absolute> or B<-relative>. B<-path_info> -is provided as a synonym. - -=item B<-query> (B<-query_string>) - -Append the query string to the URL. This can be combined with -B<-full>, B<-absolute> or B<-relative>. B<-query_string> is provided -as a synonym. - -=item B<-base> - -Generate just the protocol and net location, as in http://www.foo.com:8000 - -=item B<-rewrite> - -If Apache's mod_rewrite is turned on, then the script name and path -info probably won't match the request that the user sent. Set --rewrite=>1 (default) to return URLs that match what the user sent -(the original request URI). Set -rewrite=>0 to return URLs that match -the URL after mod_rewrite's rules have run. Because the additional -path information only makes sense in the context of the rewritten URL, --rewrite is set to false when you request path info in the URL. - -=back - -=head2 MIXING POST AND URL PARAMETERS - - $color = url_param('color'); - -It is possible for a script to receive CGI parameters in the URL as -well as in the fill-out form by creating a form that POSTs to a URL -containing a query string (a "?" mark followed by arguments). The -B<param()> method will always return the contents of the POSTed -fill-out form, ignoring the URL's query string. To retrieve URL -parameters, call the B<url_param()> method. Use it in the same way as -B<param()>. The main difference is that it allows you to read the -parameters, but not set them. - - -Under no circumstances will the contents of the URL query string -interfere with similarly-named CGI parameters in POSTed forms. If you -try to mix a URL query string with a form submitted with the GET -method, the results will not be what you expect. - -=head1 CREATING STANDARD HTML ELEMENTS: - -CGI.pm defines general HTML shortcut methods for most, if not all of -the HTML 3 and HTML 4 tags. HTML shortcuts are named after a single -HTML element and return a fragment of HTML text that you can then -print or manipulate as you like. Each shortcut returns a fragment of -HTML code that you can append to a string, save to a file, or, most -commonly, print out so that it displays in the browser window. - -This example shows how to use the HTML methods: - - print $q->blockquote( - "Many years ago on the island of", - $q->a({href=>"http://crete.org/"},"Crete"), - "there lived a Minotaur named", - $q->strong("Fred."), - ), - $q->hr; - -This results in the following HTML code (extra newlines have been -added for readability): - - <blockquote> - Many years ago on the island of - <a href="http://crete.org/">Crete</a> there lived - a minotaur named <strong>Fred.</strong> - </blockquote> - <hr> - -If you find the syntax for calling the HTML shortcuts awkward, you can -import them into your namespace and dispense with the object syntax -completely (see the next section for more details): - - use CGI ':standard'; - print blockquote( - "Many years ago on the island of", - a({href=>"http://crete.org/"},"Crete"), - "there lived a minotaur named", - strong("Fred."), - ), - hr; - -=head2 PROVIDING ARGUMENTS TO HTML SHORTCUTS - -The HTML methods will accept zero, one or multiple arguments. If you -provide no arguments, you get a single tag: - - print hr; # <hr> - -If you provide one or more string arguments, they are concatenated -together with spaces and placed between opening and closing tags: - - print h1("Chapter","1"); # <h1>Chapter 1</h1>" - -If the first argument is a hash reference, then the keys -and values of the hash become the HTML tag's attributes: - - print a({-href=>'fred.html',-target=>'_new'}, - "Open a new frame"); - - <a href="fred.html",target="_new">Open a new frame</a> - -You may dispense with the dashes in front of the attribute names if -you prefer: - - print img {src=>'fred.gif',align=>'LEFT'}; - - <img align="LEFT" src="fred.gif"> - -Sometimes an HTML tag attribute has no argument. For example, ordered -lists can be marked as COMPACT. The syntax for this is an argument that -that points to an undef string: - - print ol({compact=>undef},li('one'),li('two'),li('three')); - -Prior to CGI.pm version 2.41, providing an empty ('') string as an -attribute argument was the same as providing undef. However, this has -changed in order to accommodate those who want to create tags of the form -<img alt="">. The difference is shown in these two pieces of code: - - CODE RESULT - img({alt=>undef}) <img alt> - img({alt=>''}) <img alt=""> - -=head2 THE DISTRIBUTIVE PROPERTY OF HTML SHORTCUTS - -One of the cool features of the HTML shortcuts is that they are -distributive. If you give them an argument consisting of a -B<reference> to a list, the tag will be distributed across each -element of the list. For example, here's one way to make an ordered -list: - - print ul( - li({-type=>'disc'},['Sneezy','Doc','Sleepy','Happy']) - ); - -This example will result in HTML output that looks like this: - - <ul> - <li type="disc">Sneezy</li> - <li type="disc">Doc</li> - <li type="disc">Sleepy</li> - <li type="disc">Happy</li> - </ul> - -This is extremely useful for creating tables. For example: - - print table({-border=>undef}, - caption('When Should You Eat Your Vegetables?'), - Tr({-align=>'CENTER',-valign=>'TOP'}, - [ - th(['Vegetable', 'Breakfast','Lunch','Dinner']), - td(['Tomatoes' , 'no', 'yes', 'yes']), - td(['Broccoli' , 'no', 'no', 'yes']), - td(['Onions' , 'yes','yes', 'yes']) - ] - ) - ); - -=head2 HTML SHORTCUTS AND LIST INTERPOLATION - -Consider this bit of code: - - print blockquote(em('Hi'),'mom!')); - -It will ordinarily return the string that you probably expect, namely: - - <blockquote><em>Hi</em> mom!</blockquote> - -Note the space between the element "Hi" and the element "mom!". -CGI.pm puts the extra space there using array interpolation, which is -controlled by the magic $" variable. Sometimes this extra space is -not what you want, for example, when you are trying to align a series -of images. In this case, you can simply change the value of $" to an -empty string. - - { - local($") = ''; - print blockquote(em('Hi'),'mom!')); - } - -I suggest you put the code in a block as shown here. Otherwise the -change to $" will affect all subsequent code until you explicitly -reset it. - -=head2 NON-STANDARD HTML SHORTCUTS - -A few HTML tags don't follow the standard pattern for various -reasons. - -B<comment()> generates an HTML comment (<!-- comment -->). Call it -like - - print comment('here is my comment'); - -Because of conflicts with built-in Perl functions, the following functions -begin with initial caps: - - Select - Tr - Link - Delete - Accept - Sub - -In addition, start_html(), end_html(), start_form(), end_form(), -start_multipart_form() and all the fill-out form tags are special. -See their respective sections. - -=head2 AUTOESCAPING HTML - -By default, all HTML that is emitted by the form-generating functions -is passed through a function called escapeHTML(): - -=over 4 - -=item $escaped_string = escapeHTML("unescaped string"); - -Escape HTML formatting characters in a string. - -=back - -Provided that you have specified a character set of ISO-8859-1 (the -default), the standard HTML escaping rules will be used. The "<" -character becomes "<", ">" becomes ">", "&" becomes "&", and -the quote character becomes """. In addition, the hexadecimal -0x8b and 0x9b characters, which some browsers incorrectly interpret -as the left and right angle-bracket characters, are replaced by their -numeric character entities ("‹" and "›"). If you manually change -the charset, either by calling the charset() method explicitly or by -passing a -charset argument to header(), then B<all> characters will -be replaced by their numeric entities, since CGI.pm has no lookup -table for all the possible encodings. - -The automatic escaping does not apply to other shortcuts, such as -h1(). You should call escapeHTML() yourself on untrusted data in -order to protect your pages against nasty tricks that people may enter -into guestbooks, etc.. To change the character set, use charset(). -To turn autoescaping off completely, use autoEscape(0): - -=over 4 - -=item $charset = charset([$charset]); - -Get or set the current character set. - -=item $flag = autoEscape([$flag]); - -Get or set the value of the autoescape flag. - -=back - -=head2 PRETTY-PRINTING HTML - -By default, all the HTML produced by these functions comes out as one -long line without carriage returns or indentation. This is yuck, but -it does reduce the size of the documents by 10-20%. To get -pretty-printed output, please use L<CGI::Pretty>, a subclass -contributed by Brian Paulsen. - -=head1 CREATING FILL-OUT FORMS: - -I<General note> The various form-creating methods all return strings -to the caller, containing the tag or tags that will create the requested -form element. You are responsible for actually printing out these strings. -It's set up this way so that you can place formatting tags -around the form elements. - -I<Another note> The default values that you specify for the forms are only -used the B<first> time the script is invoked (when there is no query -string). On subsequent invocations of the script (when there is a query -string), the former values are used even if they are blank. - -If you want to change the value of a field from its previous value, you have two -choices: - -(1) call the param() method to set it. - -(2) use the -override (alias -force) parameter (a new feature in version 2.15). -This forces the default value to be used, regardless of the previous value: - - print textfield(-name=>'field_name', - -default=>'starting value', - -override=>1, - -size=>50, - -maxlength=>80); - -I<Yet another note> By default, the text and labels of form elements are -escaped according to HTML rules. This means that you can safely use -"<CLICK ME>" as the label for a button. However, it also interferes with -your ability to incorporate special HTML character sequences, such as Á, -into your fields. If you wish to turn off automatic escaping, call the -autoEscape() method with a false value immediately after creating the CGI object: - - $query = new CGI; - autoEscape(undef); - -I<A Lurking Trap!> Some of the form-element generating methods return -multiple tags. In a scalar context, the tags will be concatenated -together with spaces, or whatever is the current value of the $" -global. In a list context, the methods will return a list of -elements, allowing you to modify them if you wish. Usually you will -not notice this behavior, but beware of this: - - printf("%s\n",end_form()) - -end_form() produces several tags, and only the first of them will be -printed because the format only expects one value. - -<p> - - -=head2 CREATING AN ISINDEX TAG - - print isindex(-action=>$action); - - -or- - - print isindex($action); - -Prints out an <isindex> tag. Not very exciting. The parameter --action specifies the URL of the script to process the query. The -default is to process the query with the current script. - -=head2 STARTING AND ENDING A FORM - - print start_form(-method=>$method, - -action=>$action, - -enctype=>$encoding); - <... various form stuff ...> - print end_form; - - -or- - - print start_form($method,$action,$encoding); - <... various form stuff ...> - print end_form; - -start_form() will return a <form> tag with the optional method, -action and form encoding that you specify. The defaults are: - - method: POST - action: this script - enctype: application/x-www-form-urlencoded - -end_form() returns the closing </form> tag. - -Start_form()'s enctype argument tells the browser how to package the various -fields of the form before sending the form to the server. Two -values are possible: - -B<Note:> These methods were previously named startform() and endform(), and they -are still recognized as aliases of start_form() and end_form(). - -=over 4 - -=item B<application/x-www-form-urlencoded> - -This is the older type of encoding used by all browsers prior to -Netscape 2.0. It is compatible with many CGI scripts and is -suitable for short fields containing text data. For your -convenience, CGI.pm stores the name of this encoding -type in B<&CGI::URL_ENCODED>. - -=item B<multipart/form-data> - -This is the newer type of encoding introduced by Netscape 2.0. -It is suitable for forms that contain very large fields or that -are intended for transferring binary data. Most importantly, -it enables the "file upload" feature of Netscape 2.0 forms. For -your convenience, CGI.pm stores the name of this encoding type -in B<&CGI::MULTIPART> - -Forms that use this type of encoding are not easily interpreted -by CGI scripts unless they use CGI.pm or another library designed -to handle them. - -If XHTML is activated (the default), then forms will be automatically -created using this type of encoding. - -=back - -For compatibility, the start_form() method uses the older form of -encoding by default. If you want to use the newer form of encoding -by default, you can call B<start_multipart_form()> instead of -B<start_form()>. - -JAVASCRIPTING: The B<-name> and B<-onSubmit> parameters are provided -for use with JavaScript. The -name parameter gives the -form a name so that it can be identified and manipulated by -JavaScript functions. -onSubmit should point to a JavaScript -function that will be executed just before the form is submitted to your -server. You can use this opportunity to check the contents of the form -for consistency and completeness. If you find something wrong, you -can put up an alert box or maybe fix things up yourself. You can -abort the submission by returning false from this function. - -Usually the bulk of JavaScript functions are defined in a <script> -block in the HTML header and -onSubmit points to one of these function -call. See start_html() for details. - -=head2 FORM ELEMENTS - -After starting a form, you will typically create one or more -textfields, popup menus, radio groups and other form elements. Each -of these elements takes a standard set of named arguments. Some -elements also have optional arguments. The standard arguments are as -follows: - -=over 4 - -=item B<-name> - -The name of the field. After submission this name can be used to -retrieve the field's value using the param() method. - -=item B<-value>, B<-values> - -The initial value of the field which will be returned to the script -after form submission. Some form elements, such as text fields, take -a single scalar -value argument. Others, such as popup menus, take a -reference to an array of values. The two arguments are synonyms. - -=item B<-tabindex> - -A numeric value that sets the order in which the form element receives -focus when the user presses the tab key. Elements with lower values -receive focus first. - -=item B<-id> - -A string identifier that can be used to identify this element to -JavaScript and DHTML. - -=item B<-override> - -A boolean, which, if true, forces the element to take on the value -specified by B<-value>, overriding the sticky behavior described -earlier for the B<-nosticky> pragma. - -=item B<-onChange>, B<-onFocus>, B<-onBlur>, B<-onMouseOver>, B<-onMouseOut>, B<-onSelect> - -These are used to assign JavaScript event handlers. See the -JavaScripting section for more details. - -=back - -Other common arguments are described in the next section. In addition -to these, all attributes described in the HTML specifications are -supported. - -=head2 CREATING A TEXT FIELD - - print textfield(-name=>'field_name', - -value=>'starting value', - -size=>50, - -maxlength=>80); - -or- - - print textfield('field_name','starting value',50,80); - -textfield() will return a text input field. - -=over 4 - -=item B<Parameters> - -=item 1. - -The first parameter is the required name for the field (-name). - -=item 2. - -The optional second parameter is the default starting value for the field -contents (-value, formerly known as -default). - -=item 3. - -The optional third parameter is the size of the field in - characters (-size). - -=item 4. - -The optional fourth parameter is the maximum number of characters the - field will accept (-maxlength). - -=back - -As with all these methods, the field will be initialized with its -previous contents from earlier invocations of the script. -When the form is processed, the value of the text field can be -retrieved with: - - $value = param('foo'); - -If you want to reset it from its initial value after the script has been -called once, you can do so like this: - - param('foo',"I'm taking over this value!"); - -=head2 CREATING A BIG TEXT FIELD - - print textarea(-name=>'foo', - -default=>'starting value', - -rows=>10, - -columns=>50); - - -or - - print textarea('foo','starting value',10,50); - -textarea() is just like textfield, but it allows you to specify -rows and columns for a multiline text entry box. You can provide -a starting value for the field, which can be long and contain -multiple lines. - -=head2 CREATING A PASSWORD FIELD - - print password_field(-name=>'secret', - -value=>'starting value', - -size=>50, - -maxlength=>80); - -or- - - print password_field('secret','starting value',50,80); - -password_field() is identical to textfield(), except that its contents -will be starred out on the web page. - -=head2 CREATING A FILE UPLOAD FIELD - - print filefield(-name=>'uploaded_file', - -default=>'starting value', - -size=>50, - -maxlength=>80); - -or- - - print filefield('uploaded_file','starting value',50,80); - -filefield() will return a file upload field for Netscape 2.0 browsers. -In order to take full advantage of this I<you must use the new -multipart encoding scheme> for the form. You can do this either -by calling B<start_form()> with an encoding type of B<&CGI::MULTIPART>, -or by calling the new method B<start_multipart_form()> instead of -vanilla B<start_form()>. - -=over 4 - -=item B<Parameters> - -=item 1. - -The first parameter is the required name for the field (-name). - -=item 2. - -The optional second parameter is the starting value for the field contents -to be used as the default file name (-default). - -For security reasons, browsers don't pay any attention to this field, -and so the starting value will always be blank. Worse, the field -loses its "sticky" behavior and forgets its previous contents. The -starting value field is called for in the HTML specification, however, -and possibly some browser will eventually provide support for it. - -=item 3. - -The optional third parameter is the size of the field in -characters (-size). - -=item 4. - -The optional fourth parameter is the maximum number of characters the -field will accept (-maxlength). - -=back - -When the form is processed, you can retrieve the entered filename -by calling param(): - - $filename = param('uploaded_file'); - -Different browsers will return slightly different things for the -name. Some browsers return the filename only. Others return the full -path to the file, using the path conventions of the user's machine. -Regardless, the name returned is always the name of the file on the -I<user's> machine, and is unrelated to the name of the temporary file -that CGI.pm creates during upload spooling (see below). - -The filename returned is also a file handle. You can read the contents -of the file using standard Perl file reading calls: - - # Read a text file and print it out - while (<$filename>) { - print; - } - - # Copy a binary file to somewhere safe - open (OUTFILE,">>/usr/local/web/users/feedback"); - while ($bytesread=read($filename,$buffer,1024)) { - print OUTFILE $buffer; - } - -However, there are problems with the dual nature of the upload fields. -If you C<use strict>, then Perl will complain when you try to use a -string as a filehandle. You can get around this by placing the file -reading code in a block containing the C<no strict> pragma. More -seriously, it is possible for the remote user to type garbage into the -upload field, in which case what you get from param() is not a -filehandle at all, but a string. - -To be safe, use the I<upload()> function (new in version 2.47). When -called with the name of an upload field, I<upload()> returns a -filehandle-like object, or undef if the parameter is not a valid -filehandle. - - $fh = upload('uploaded_file'); - while (<$fh>) { - print; - } - -In a list context, upload() will return an array of filehandles. -This makes it possible to create forms that use the same name for -multiple upload fields. - -This is the recommended idiom. - -The lightweight filehandle returned by CGI.pm is not compatible with -IO::Handle; for example, it does not have read() or getline() -functions, but instead must be manipulated using read($fh) or -<$fh>. To get a compatible IO::Handle object, call the handle's -handle() method: - - my $real_io_handle = upload('uploaded_file')->handle; - -When a file is uploaded the browser usually sends along some -information along with it in the format of headers. The information -usually includes the MIME content type. Future browsers may send -other information as well (such as modification date and size). To -retrieve this information, call uploadInfo(). It returns a reference to -a hash containing all the document headers. - - $filename = param('uploaded_file'); - $type = uploadInfo($filename)->{'Content-Type'}; - unless ($type eq 'text/html') { - die "HTML FILES ONLY!"; - } - -If you are using a machine that recognizes "text" and "binary" data -modes, be sure to understand when and how to use them (see the Camel book). -Otherwise you may find that binary files are corrupted during file -uploads. - -There are occasionally problems involving parsing the uploaded file. -This usually happens when the user presses "Stop" before the upload is -finished. In this case, CGI.pm will return undef for the name of the -uploaded file and set I<cgi_error()> to the string "400 Bad request -(malformed multipart POST)". This error message is designed so that -you can incorporate it into a status code to be sent to the browser. -Example: - - $file = upload('uploaded_file'); - if (!$file && cgi_error) { - print header(-status=>cgi_error); - exit 0; - } - -You are free to create a custom HTML page to complain about the error, -if you wish. - -You can set up a callback that will be called whenever a file upload -is being read during the form processing. This is much like the -UPLOAD_HOOK facility available in Apache::Request, with the exception -that the first argument to the callback is an Apache::Upload object, -here it's the remote filename. - - $q = CGI->new(\&hook [,$data [,$use_tempfile]]); - - sub hook - { - my ($filename, $buffer, $bytes_read, $data) = @_; - print "Read $bytes_read bytes of $filename\n"; - } - -The $data field is optional; it lets you pass configuration -information (e.g. a database handle) to your hook callback. - -The $use_tempfile field is a flag that lets you turn on and off -CGI.pm's use of a temporary disk-based file during file upload. If you -set this to a FALSE value (default true) then param('uploaded_file') -will no longer work, and the only way to get at the uploaded data is -via the hook you provide. - -If using the function-oriented interface, call the CGI::upload_hook() -method before calling param() or any other CGI functions: - - CGI::upload_hook(\&hook [,$data [,$use_tempfile]]); - -This method is not exported by default. You will have to import it -explicitly if you wish to use it without the CGI:: prefix. - -If you are using CGI.pm on a Windows platform and find that binary -files get slightly larger when uploaded but that text files remain the -same, then you have forgotten to activate binary mode on the output -filehandle. Be sure to call binmode() on any handle that you create -to write the uploaded file to disk. - -JAVASCRIPTING: The B<-onChange>, B<-onFocus>, B<-onBlur>, -B<-onMouseOver>, B<-onMouseOut> and B<-onSelect> parameters are -recognized. See textfield() for details. - -=head2 CREATING A POPUP MENU - - print popup_menu('menu_name', - ['eenie','meenie','minie'], - 'meenie'); - - -or- - - %labels = ('eenie'=>'your first choice', - 'meenie'=>'your second choice', - 'minie'=>'your third choice'); - %attributes = ('eenie'=>{'class'=>'class of first choice'}); - print popup_menu('menu_name', - ['eenie','meenie','minie'], - 'meenie',\%labels,\%attributes); - - -or (named parameter style)- - - print popup_menu(-name=>'menu_name', - -values=>['eenie','meenie','minie'], - -default=>['meenie','minie'], - -labels=>\%labels, - -attributes=>\%attributes); - -popup_menu() creates a menu. - -=over 4 - -=item 1. - -The required first argument is the menu's name (-name). - -=item 2. - -The required second argument (-values) is an array B<reference> -containing the list of menu items in the menu. You can pass the -method an anonymous array, as shown in the example, or a reference to -a named array, such as "\@foo". - -=item 3. - -The optional third parameter (-default) is the name of the default -menu choice. If not specified, the first item will be the default. -The values of the previous choice will be maintained across -queries. Pass an array reference to select multiple defaults. - -=item 4. - -The optional fourth parameter (-labels) is provided for people who -want to use different values for the user-visible label inside the -popup menu and the value returned to your script. It's a pointer to an -hash relating menu values to user-visible labels. If you -leave this parameter blank, the menu values will be displayed by -default. (You can also leave a label undefined if you want to). - -=item 5. - -The optional fifth parameter (-attributes) is provided to assign -any of the common HTML attributes to an individual menu item. It's -a pointer to a hash relating menu values to another -hash with the attribute's name as the key and the -attribute's value as the value. - -=back - -When the form is processed, the selected value of the popup menu can -be retrieved using: - - $popup_menu_value = param('menu_name'); - -=head2 CREATING AN OPTION GROUP - -Named parameter style - - print popup_menu(-name=>'menu_name', - -values=>[qw/eenie meenie minie/, - optgroup(-name=>'optgroup_name', - -values => ['moe','catch'], - -attributes=>{'catch'=>{'class'=>'red'}})], - -labels=>{'eenie'=>'one', - 'meenie'=>'two', - 'minie'=>'three'}, - -default=>'meenie'); - - Old style - print popup_menu('menu_name', - ['eenie','meenie','minie', - optgroup('optgroup_name', ['moe', 'catch'], - {'catch'=>{'class'=>'red'}})],'meenie', - {'eenie'=>'one','meenie'=>'two','minie'=>'three'}); - -optgroup() creates an option group within a popup menu. - -=over 4 - -=item 1. - -The required first argument (B<-name>) is the label attribute of the -optgroup and is B<not> inserted in the parameter list of the query. - -=item 2. - -The required second argument (B<-values>) is an array reference -containing the list of menu items in the menu. You can pass the -method an anonymous array, as shown in the example, or a reference -to a named array, such as \@foo. If you pass a HASH reference, -the keys will be used for the menu values, and the values will be -used for the menu labels (see -labels below). - -=item 3. - -The optional third parameter (B<-labels>) allows you to pass a reference -to a hash containing user-visible labels for one or more -of the menu items. You can use this when you want the user to see one -menu string, but have the browser return your program a different one. -If you don't specify this, the value string will be used instead -("eenie", "meenie" and "minie" in this example). This is equivalent -to using a hash reference for the -values parameter. - -=item 4. - -An optional fourth parameter (B<-labeled>) can be set to a true value -and indicates that the values should be used as the label attribute -for each option element within the optgroup. - -=item 5. - -An optional fifth parameter (-novals) can be set to a true value and -indicates to suppress the val attribute in each option element within -the optgroup. - -See the discussion on optgroup at W3C -(http://www.w3.org/TR/REC-html40/interact/forms.html#edef-OPTGROUP) -for details. - -=item 6. - -An optional sixth parameter (-attributes) is provided to assign -any of the common HTML attributes to an individual menu item. It's -a pointer to a hash relating menu values to another -hash with the attribute's name as the key and the -attribute's value as the value. - -=back - -=head2 CREATING A SCROLLING LIST - - print scrolling_list('list_name', - ['eenie','meenie','minie','moe'], - ['eenie','moe'],5,'true',{'moe'=>{'class'=>'red'}}); - -or- - - print scrolling_list('list_name', - ['eenie','meenie','minie','moe'], - ['eenie','moe'],5,'true', - \%labels,%attributes); - - -or- - - print scrolling_list(-name=>'list_name', - -values=>['eenie','meenie','minie','moe'], - -default=>['eenie','moe'], - -size=>5, - -multiple=>'true', - -labels=>\%labels, - -attributes=>\%attributes); - -scrolling_list() creates a scrolling list. - -=over 4 - -=item B<Parameters:> - -=item 1. - -The first and second arguments are the list name (-name) and values -(-values). As in the popup menu, the second argument should be an -array reference. - -=item 2. - -The optional third argument (-default) can be either a reference to a -list containing the values to be selected by default, or can be a -single value to select. If this argument is missing or undefined, -then nothing is selected when the list first appears. In the named -parameter version, you can use the synonym "-defaults" for this -parameter. - -=item 3. - -The optional fourth argument is the size of the list (-size). - -=item 4. - -The optional fifth argument can be set to true to allow multiple -simultaneous selections (-multiple). Otherwise only one selection -will be allowed at a time. - -=item 5. - -The optional sixth argument is a pointer to a hash -containing long user-visible labels for the list items (-labels). -If not provided, the values will be displayed. - -=item 6. - -The optional sixth parameter (-attributes) is provided to assign -any of the common HTML attributes to an individual menu item. It's -a pointer to a hash relating menu values to another -hash with the attribute's name as the key and the -attribute's value as the value. - -When this form is processed, all selected list items will be returned as -a list under the parameter name 'list_name'. The values of the -selected items can be retrieved with: - - @selected = param('list_name'); - -=back - -=head2 CREATING A GROUP OF RELATED CHECKBOXES - - print checkbox_group(-name=>'group_name', - -values=>['eenie','meenie','minie','moe'], - -default=>['eenie','moe'], - -linebreak=>'true', - -disabled => ['moe'], - -labels=>\%labels, - -attributes=>\%attributes); - - print checkbox_group('group_name', - ['eenie','meenie','minie','moe'], - ['eenie','moe'],'true',\%labels, - {'moe'=>{'class'=>'red'}}); - - HTML3-COMPATIBLE BROWSERS ONLY: - - print checkbox_group(-name=>'group_name', - -values=>['eenie','meenie','minie','moe'], - -rows=2,-columns=>2); - - -checkbox_group() creates a list of checkboxes that are related -by the same name. - -=over 4 - -=item B<Parameters:> - -=item 1. - -The first and second arguments are the checkbox name and values, -respectively (-name and -values). As in the popup menu, the second -argument should be an array reference. These values are used for the -user-readable labels printed next to the checkboxes as well as for the -values passed to your script in the query string. - -=item 2. - -The optional third argument (-default) can be either a reference to a -list containing the values to be checked by default, or can be a -single value to checked. If this argument is missing or undefined, -then nothing is selected when the list first appears. - -=item 3. - -The optional fourth argument (-linebreak) can be set to true to place -line breaks between the checkboxes so that they appear as a vertical -list. Otherwise, they will be strung together on a horizontal line. - -=back - - -The optional b<-labels> argument is a pointer to a hash -relating the checkbox values to the user-visible labels that will be -printed next to them. If not provided, the values will be used as the -default. - - -The optional parameters B<-rows>, and B<-columns> cause -checkbox_group() to return an HTML3 compatible table containing the -checkbox group formatted with the specified number of rows and -columns. You can provide just the -columns parameter if you wish; -checkbox_group will calculate the correct number of rows for you. - -The option b<-disabled> takes an array of checkbox values and disables -them by greying them out (this may not be supported by all browsers). - -The optional B<-attributes> argument is provided to assign any of the -common HTML attributes to an individual menu item. It's a pointer to -a hash relating menu values to another hash -with the attribute's name as the key and the attribute's value as the -value. - -The optional B<-tabindex> argument can be used to control the order in which -radio buttons receive focus when the user presses the tab button. If -passed a scalar numeric value, the first element in the group will -receive this tab index and subsequent elements will be incremented by -one. If given a reference to an array of radio button values, then -the indexes will be jiggered so that the order specified in the array -will correspond to the tab order. You can also pass a reference to a -hash in which the hash keys are the radio button values and the values -are the tab indexes of each button. Examples: - - -tabindex => 100 # this group starts at index 100 and counts up - -tabindex => ['moe','minie','eenie','meenie'] # tab in this order - -tabindex => {meenie=>100,moe=>101,minie=>102,eenie=>200} # tab in this order - -The optional B<-labelattributes> argument will contain attributes -attached to the <label> element that surrounds each button. - -When the form is processed, all checked boxes will be returned as -a list under the parameter name 'group_name'. The values of the -"on" checkboxes can be retrieved with: - - @turned_on = param('group_name'); - -The value returned by checkbox_group() is actually an array of button -elements. You can capture them and use them within tables, lists, -or in other creative ways: - - @h = checkbox_group(-name=>'group_name',-values=>\@values); - &use_in_creative_way(@h); - -=head2 CREATING A STANDALONE CHECKBOX - - print checkbox(-name=>'checkbox_name', - -checked=>1, - -value=>'ON', - -label=>'CLICK ME'); - - -or- - - print checkbox('checkbox_name','checked','ON','CLICK ME'); - -checkbox() is used to create an isolated checkbox that isn't logically -related to any others. - -=over 4 - -=item B<Parameters:> - -=item 1. - -The first parameter is the required name for the checkbox (-name). It -will also be used for the user-readable label printed next to the -checkbox. - -=item 2. - -The optional second parameter (-checked) specifies that the checkbox -is turned on by default. Synonyms are -selected and -on. - -=item 3. - -The optional third parameter (-value) specifies the value of the -checkbox when it is checked. If not provided, the word "on" is -assumed. - -=item 4. - -The optional fourth parameter (-label) is the user-readable label to -be attached to the checkbox. If not provided, the checkbox name is -used. - -=back - -The value of the checkbox can be retrieved using: - - $turned_on = param('checkbox_name'); - -=head2 CREATING A RADIO BUTTON GROUP - - print radio_group(-name=>'group_name', - -values=>['eenie','meenie','minie'], - -default=>'meenie', - -linebreak=>'true', - -labels=>\%labels, - -attributes=>\%attributes); - - -or- - - print radio_group('group_name',['eenie','meenie','minie'], - 'meenie','true',\%labels,\%attributes); - - - HTML3-COMPATIBLE BROWSERS ONLY: - - print radio_group(-name=>'group_name', - -values=>['eenie','meenie','minie','moe'], - -rows=2,-columns=>2); - -radio_group() creates a set of logically-related radio buttons -(turning one member of the group on turns the others off) - -=over 4 - -=item B<Parameters:> - -=item 1. - -The first argument is the name of the group and is required (-name). - -=item 2. - -The second argument (-values) is the list of values for the radio -buttons. The values and the labels that appear on the page are -identical. Pass an array I<reference> in the second argument, either -using an anonymous array, as shown, or by referencing a named array as -in "\@foo". - -=item 3. - -The optional third parameter (-default) is the name of the default -button to turn on. If not specified, the first item will be the -default. You can provide a nonexistent button name, such as "-" to -start up with no buttons selected. - -=item 4. - -The optional fourth parameter (-linebreak) can be set to 'true' to put -line breaks between the buttons, creating a vertical list. - -=item 5. - -The optional fifth parameter (-labels) is a pointer to an associative -array relating the radio button values to user-visible labels to be -used in the display. If not provided, the values themselves are -displayed. - -=back - - -All modern browsers can take advantage of the optional parameters -B<-rows>, and B<-columns>. These parameters cause radio_group() to -return an HTML3 compatible table containing the radio group formatted -with the specified number of rows and columns. You can provide just -the -columns parameter if you wish; radio_group will calculate the -correct number of rows for you. - -To include row and column headings in the returned table, you -can use the B<-rowheaders> and B<-colheaders> parameters. Both -of these accept a pointer to an array of headings to use. -The headings are just decorative. They don't reorganize the -interpretation of the radio buttons -- they're still a single named -unit. - -The optional B<-tabindex> argument can be used to control the order in which -radio buttons receive focus when the user presses the tab button. If -passed a scalar numeric value, the first element in the group will -receive this tab index and subsequent elements will be incremented by -one. If given a reference to an array of radio button values, then -the indexes will be jiggered so that the order specified in the array -will correspond to the tab order. You can also pass a reference to a -hash in which the hash keys are the radio button values and the values -are the tab indexes of each button. Examples: - - -tabindex => 100 # this group starts at index 100 and counts up - -tabindex => ['moe','minie','eenie','meenie'] # tab in this order - -tabindex => {meenie=>100,moe=>101,minie=>102,eenie=>200} # tab in this order - - -The optional B<-attributes> argument is provided to assign any of the -common HTML attributes to an individual menu item. It's a pointer to -a hash relating menu values to another hash -with the attribute's name as the key and the attribute's value as the -value. - -The optional B<-labelattributes> argument will contain attributes -attached to the <label> element that surrounds each button. - -When the form is processed, the selected radio button can -be retrieved using: - - $which_radio_button = param('group_name'); - -The value returned by radio_group() is actually an array of button -elements. You can capture them and use them within tables, lists, -or in other creative ways: - - @h = radio_group(-name=>'group_name',-values=>\@values); - &use_in_creative_way(@h); - -=head2 CREATING A SUBMIT BUTTON - - print submit(-name=>'button_name', - -value=>'value'); - - -or- - - print submit('button_name','value'); - -submit() will create the query submission button. Every form -should have one of these. - -=over 4 - -=item B<Parameters:> - -=item 1. - -The first argument (-name) is optional. You can give the button a -name if you have several submission buttons in your form and you want -to distinguish between them. - -=item 2. - -The second argument (-value) is also optional. This gives the button -a value that will be passed to your script in the query string. The -name will also be used as the user-visible label. - -=item 3. - -You can use -label as an alias for -value. I always get confused -about which of -name and -value changes the user-visible label on the -button. - -=back - -You can figure out which button was pressed by using different -values for each one: - - $which_one = param('button_name'); - -=head2 CREATING A RESET BUTTON - - print reset - -reset() creates the "reset" button. Note that it restores the -form to its value from the last time the script was called, -NOT necessarily to the defaults. - -Note that this conflicts with the Perl reset() built-in. Use -CORE::reset() to get the original reset function. - -=head2 CREATING A DEFAULT BUTTON - - print defaults('button_label') - -defaults() creates a button that, when invoked, will cause the -form to be completely reset to its defaults, wiping out all the -changes the user ever made. - -=head2 CREATING A HIDDEN FIELD - - print hidden(-name=>'hidden_name', - -default=>['value1','value2'...]); - - -or- - - print hidden('hidden_name','value1','value2'...); - -hidden() produces a text field that can't be seen by the user. It -is useful for passing state variable information from one invocation -of the script to the next. - -=over 4 - -=item B<Parameters:> - -=item 1. - -The first argument is required and specifies the name of this -field (-name). - -=item 2. - -The second argument is also required and specifies its value -(-default). In the named parameter style of calling, you can provide -a single value here or a reference to a whole list - -=back - -Fetch the value of a hidden field this way: - - $hidden_value = param('hidden_name'); - -Note, that just like all the other form elements, the value of a -hidden field is "sticky". If you want to replace a hidden field with -some other values after the script has been called once you'll have to -do it manually: - - param('hidden_name','new','values','here'); - -=head2 CREATING A CLICKABLE IMAGE BUTTON - - print image_button(-name=>'button_name', - -src=>'/source/URL', - -align=>'MIDDLE'); - - -or- - - print image_button('button_name','/source/URL','MIDDLE'); - -image_button() produces a clickable image. When it's clicked on the -position of the click is returned to your script as "button_name.x" -and "button_name.y", where "button_name" is the name you've assigned -to it. - -=over 4 - -=item B<Parameters:> - -=item 1. - -The first argument (-name) is required and specifies the name of this -field. - -=item 2. - -The second argument (-src) is also required and specifies the URL - -=item 3. -The third option (-align, optional) is an alignment type, and may be -TOP, BOTTOM or MIDDLE - -=back - -Fetch the value of the button this way: - $x = param('button_name.x'); - $y = param('button_name.y'); - -=head2 CREATING A JAVASCRIPT ACTION BUTTON - - print button(-name=>'button_name', - -value=>'user visible label', - -onClick=>"do_something()"); - - -or- - - print button('button_name',"do_something()"); - -button() produces a button that is compatible with Netscape 2.0's -JavaScript. When it's pressed the fragment of JavaScript code -pointed to by the B<-onClick> parameter will be executed. - -=head1 HTTP COOKIES - -Browsers support a so-called "cookie" designed to help maintain state -within a browser session. CGI.pm has several methods that support -cookies. - -A cookie is a name=value pair much like the named parameters in a CGI -query string. CGI scripts create one or more cookies and send -them to the browser in the HTTP header. The browser maintains a list -of cookies that belong to a particular Web server, and returns them -to the CGI script during subsequent interactions. - -In addition to the required name=value pair, each cookie has several -optional attributes: - -=over 4 - -=item 1. an expiration time - -This is a time/date string (in a special GMT format) that indicates -when a cookie expires. The cookie will be saved and returned to your -script until this expiration date is reached if the user exits -the browser and restarts it. If an expiration date isn't specified, the cookie -will remain active until the user quits the browser. - -=item 2. a domain - -This is a partial or complete domain name for which the cookie is -valid. The browser will return the cookie to any host that matches -the partial domain name. For example, if you specify a domain name -of ".capricorn.com", then the browser will return the cookie to -Web servers running on any of the machines "www.capricorn.com", -"www2.capricorn.com", "feckless.capricorn.com", etc. Domain names -must contain at least two periods to prevent attempts to match -on top level domains like ".edu". If no domain is specified, then -the browser will only return the cookie to servers on the host the -cookie originated from. - -=item 3. a path - -If you provide a cookie path attribute, the browser will check it -against your script's URL before returning the cookie. For example, -if you specify the path "/cgi-bin", then the cookie will be returned -to each of the scripts "/cgi-bin/tally.pl", "/cgi-bin/order.pl", -and "/cgi-bin/customer_service/complain.pl", but not to the script -"/cgi-private/site_admin.pl". By default, path is set to "/", which -causes the cookie to be sent to any CGI script on your site. - -=item 4. a "secure" flag - -If the "secure" attribute is set, the cookie will only be sent to your -script if the CGI request is occurring on a secure channel, such as SSL. - -=back - -The interface to HTTP cookies is the B<cookie()> method: - - $cookie = cookie(-name=>'sessionID', - -value=>'xyzzy', - -expires=>'+1h', - -path=>'/cgi-bin/database', - -domain=>'.capricorn.org', - -secure=>1); - print header(-cookie=>$cookie); - -B<cookie()> creates a new cookie. Its parameters include: - -=over 4 - -=item B<-name> - -The name of the cookie (required). This can be any string at all. -Although browsers limit their cookie names to non-whitespace -alphanumeric characters, CGI.pm removes this restriction by escaping -and unescaping cookies behind the scenes. - -=item B<-value> - -The value of the cookie. This can be any scalar value, -array reference, or even hash reference. For example, -you can store an entire hash into a cookie this way: - - $cookie=cookie(-name=>'family information', - -value=>\%childrens_ages); - -=item B<-path> - -The optional partial path for which this cookie will be valid, as described -above. - -=item B<-domain> - -The optional partial domain for which this cookie will be valid, as described -above. - -=item B<-expires> - -The optional expiration date for this cookie. The format is as described -in the section on the B<header()> method: - - "+1h" one hour from now - -=item B<-secure> - -If set to true, this cookie will only be used within a secure -SSL session. - -=back - -The cookie created by cookie() must be incorporated into the HTTP -header within the string returned by the header() method: - - use CGI ':standard'; - print header(-cookie=>$my_cookie); - -To create multiple cookies, give header() an array reference: - - $cookie1 = cookie(-name=>'riddle_name', - -value=>"The Sphynx's Question"); - $cookie2 = cookie(-name=>'answers', - -value=>\%answers); - print header(-cookie=>[$cookie1,$cookie2]); - -To retrieve a cookie, request it by name by calling cookie() method -without the B<-value> parameter. This example uses the object-oriented -form: - - use CGI; - $query = new CGI; - $riddle = $query->cookie('riddle_name'); - %answers = $query->cookie('answers'); - -Cookies created with a single scalar value, such as the "riddle_name" -cookie, will be returned in that form. Cookies with array and hash -values can also be retrieved. - -The cookie and CGI namespaces are separate. If you have a parameter -named 'answers' and a cookie named 'answers', the values retrieved by -param() and cookie() are independent of each other. However, it's -simple to turn a CGI parameter into a cookie, and vice-versa: - - # turn a CGI parameter into a cookie - $c=cookie(-name=>'answers',-value=>[param('answers')]); - # vice-versa - param(-name=>'answers',-value=>[cookie('answers')]); - -If you call cookie() without any parameters, it will return a list of -the names of all cookies passed to your script: - - @cookies = cookie(); - -See the B<cookie.cgi> example script for some ideas on how to use -cookies effectively. - -=head1 WORKING WITH FRAMES - -It's possible for CGI.pm scripts to write into several browser panels -and windows using the HTML 4 frame mechanism. There are three -techniques for defining new frames programmatically: - -=over 4 - -=item 1. Create a <Frameset> document - -After writing out the HTTP header, instead of creating a standard -HTML document using the start_html() call, create a <frameset> -document that defines the frames on the page. Specify your script(s) -(with appropriate parameters) as the SRC for each of the frames. - -There is no specific support for creating <frameset> sections -in CGI.pm, but the HTML is very simple to write. See the frame -documentation in Netscape's home pages for details - - http://wp.netscape.com/assist/net_sites/frames.html - -=item 2. Specify the destination for the document in the HTTP header - -You may provide a B<-target> parameter to the header() method: - - print header(-target=>'ResultsWindow'); - -This will tell the browser to load the output of your script into the -frame named "ResultsWindow". If a frame of that name doesn't already -exist, the browser will pop up a new window and load your script's -document into that. There are a number of magic names that you can -use for targets. See the frame documents on Netscape's home pages for -details. - -=item 3. Specify the destination for the document in the <form> tag - -You can specify the frame to load in the FORM tag itself. With -CGI.pm it looks like this: - - print start_form(-target=>'ResultsWindow'); - -When your script is reinvoked by the form, its output will be loaded -into the frame named "ResultsWindow". If one doesn't already exist -a new window will be created. - -=back - -The script "frameset.cgi" in the examples directory shows one way to -create pages in which the fill-out form and the response live in -side-by-side frames. - -=head1 SUPPORT FOR JAVASCRIPT - -The usual way to use JavaScript is to define a set of functions in a -<SCRIPT> block inside the HTML header and then to register event -handlers in the various elements of the page. Events include such -things as the mouse passing over a form element, a button being -clicked, the contents of a text field changing, or a form being -submitted. When an event occurs that involves an element that has -registered an event handler, its associated JavaScript code gets -called. - -The elements that can register event handlers include the <BODY> of an -HTML document, hypertext links, all the various elements of a fill-out -form, and the form itself. There are a large number of events, and -each applies only to the elements for which it is relevant. Here is a -partial list: - -=over 4 - -=item B<onLoad> - -The browser is loading the current document. Valid in: - - + The HTML <BODY> section only. - -=item B<onUnload> - -The browser is closing the current page or frame. Valid for: - - + The HTML <BODY> section only. - -=item B<onSubmit> - -The user has pressed the submit button of a form. This event happens -just before the form is submitted, and your function can return a -value of false in order to abort the submission. Valid for: - - + Forms only. - -=item B<onClick> - -The mouse has clicked on an item in a fill-out form. Valid for: - - + Buttons (including submit, reset, and image buttons) - + Checkboxes - + Radio buttons - -=item B<onChange> - -The user has changed the contents of a field. Valid for: - - + Text fields - + Text areas - + Password fields - + File fields - + Popup Menus - + Scrolling lists - -=item B<onFocus> - -The user has selected a field to work with. Valid for: - - + Text fields - + Text areas - + Password fields - + File fields - + Popup Menus - + Scrolling lists - -=item B<onBlur> - -The user has deselected a field (gone to work somewhere else). Valid -for: - - + Text fields - + Text areas - + Password fields - + File fields - + Popup Menus - + Scrolling lists - -=item B<onSelect> - -The user has changed the part of a text field that is selected. Valid -for: - - + Text fields - + Text areas - + Password fields - + File fields - -=item B<onMouseOver> - -The mouse has moved over an element. - - + Text fields - + Text areas - + Password fields - + File fields - + Popup Menus - + Scrolling lists - -=item B<onMouseOut> - -The mouse has moved off an element. - - + Text fields - + Text areas - + Password fields - + File fields - + Popup Menus - + Scrolling lists - -=back - -In order to register a JavaScript event handler with an HTML element, -just use the event name as a parameter when you call the corresponding -CGI method. For example, to have your validateAge() JavaScript code -executed every time the textfield named "age" changes, generate the -field like this: - - print textfield(-name=>'age',-onChange=>"validateAge(this)"); - -This example assumes that you've already declared the validateAge() -function by incorporating it into a <SCRIPT> block. The CGI.pm -start_html() method provides a convenient way to create this section. - -Similarly, you can create a form that checks itself over for -consistency and alerts the user if some essential value is missing by -creating it this way: - print startform(-onSubmit=>"validateMe(this)"); - -See the javascript.cgi script for a demonstration of how this all -works. - - -=head1 LIMITED SUPPORT FOR CASCADING STYLE SHEETS - -CGI.pm has limited support for HTML3's cascading style sheets (css). -To incorporate a stylesheet into your document, pass the -start_html() method a B<-style> parameter. The value of this -parameter may be a scalar, in which case it is treated as the source -URL for the stylesheet, or it may be a hash reference. In the latter -case you should provide the hash with one or more of B<-src> or -B<-code>. B<-src> points to a URL where an externally-defined -stylesheet can be found. B<-code> points to a scalar value to be -incorporated into a <style> section. Style definitions in B<-code> -override similarly-named ones in B<-src>, hence the name "cascading." - -You may also specify the type of the stylesheet by adding the optional -B<-type> parameter to the hash pointed to by B<-style>. If not -specified, the style defaults to 'text/css'. - -To refer to a style within the body of your document, add the -B<-class> parameter to any HTML element: - - print h1({-class=>'Fancy'},'Welcome to the Party'); - -Or define styles on the fly with the B<-style> parameter: - - print h1({-style=>'Color: red;'},'Welcome to Hell'); - -You may also use the new B<span()> element to apply a style to a -section of text: - - print span({-style=>'Color: red;'}, - h1('Welcome to Hell'), - "Where did that handbasket get to?" - ); - -Note that you must import the ":html3" definitions to have the -B<span()> method available. Here's a quick and dirty example of using -CSS's. See the CSS specification at -http://www.w3.org/pub/WWW/TR/Wd-css-1.html for more information. - - use CGI qw/:standard :html3/; - - #here's a stylesheet incorporated directly into the page - $newStyle=<<END; - <!-- - P.Tip { - margin-right: 50pt; - margin-left: 50pt; - color: red; - } - P.Alert { - font-size: 30pt; - font-family: sans-serif; - color: red; - } - --> - END - print header(); - print start_html( -title=>'CGI with Style', - -style=>{-src=>'http://www.capricorn.com/style/st1.css', - -code=>$newStyle} - ); - print h1('CGI with Style'), - p({-class=>'Tip'}, - "Better read the cascading style sheet spec before playing with this!"), - span({-style=>'color: magenta'}, - "Look Mom, no hands!", - p(), - "Whooo wee!" - ); - print end_html; - -Pass an array reference to B<-code> or B<-src> in order to incorporate -multiple stylesheets into your document. - -Should you wish to incorporate a verbatim stylesheet that includes -arbitrary formatting in the header, you may pass a -verbatim tag to -the -style hash, as follows: - -print start_html (-style => {-verbatim => '@import url("/server-common/css/'.$cssFile.'");', - -src => '/server-common/css/core.css'}); - - -This will generate an HTML header that contains this: - - <link rel="stylesheet" type="text/css" href="/server-common/css/core.css"> - <style type="text/css"> - @import url("/server-common/css/main.css"); - </style> - -Any additional arguments passed in the -style value will be -incorporated into the <link> tag. For example: - - start_html(-style=>{-src=>['/styles/print.css','/styles/layout.css'], - -media => 'all'}); - -This will give: - - <link rel="stylesheet" type="text/css" href="/styles/print.css" media="all"/> - <link rel="stylesheet" type="text/css" href="/styles/layout.css" media="all"/> - -<p> - -To make more complicated <link> tags, use the Link() function -and pass it to start_html() in the -head argument, as in: - - @h = (Link({-rel=>'stylesheet',-type=>'text/css',-src=>'/ss/ss.css',-media=>'all'}), - Link({-rel=>'stylesheet',-type=>'text/css',-src=>'/ss/fred.css',-media=>'paper'})); - print start_html({-head=>\@h}) - -To create primary and "alternate" stylesheet, use the B<-alternate> option: - - start_html(-style=>{-src=>[ - {-src=>'/styles/print.css'}, - {-src=>'/styles/alt.css',-alternate=>1} - ] - }); - -=head1 DEBUGGING - -If you are running the script from the command line or in the perl -debugger, you can pass the script a list of keywords or -parameter=value pairs on the command line or from standard input (you -don't have to worry about tricking your script into reading from -environment variables). You can pass keywords like this: - - your_script.pl keyword1 keyword2 keyword3 - -or this: - - your_script.pl keyword1+keyword2+keyword3 - -or this: - - your_script.pl name1=value1 name2=value2 - -or this: - - your_script.pl name1=value1&name2=value2 - -To turn off this feature, use the -no_debug pragma. - -To test the POST method, you may enable full debugging with the -debug -pragma. This will allow you to feed newline-delimited name=value -pairs to the script on standard input. - -When debugging, you can use quotes and backslashes to escape -characters in the familiar shell manner, letting you place -spaces and other funny characters in your parameter=value -pairs: - - your_script.pl "name1='I am a long value'" "name2=two\ words" - -Finally, you can set the path info for the script by prefixing the first -name/value parameter with the path followed by a question mark (?): - - your_script.pl /your/path/here?name1=value1&name2=value2 - -=head2 DUMPING OUT ALL THE NAME/VALUE PAIRS - -The Dump() method produces a string consisting of all the query's -name/value pairs formatted nicely as a nested list. This is useful -for debugging purposes: - - print Dump - - -Produces something that looks like: - - <ul> - <li>name1 - <ul> - <li>value1 - <li>value2 - </ul> - <li>name2 - <ul> - <li>value1 - </ul> - </ul> - -As a shortcut, you can interpolate the entire CGI object into a string -and it will be replaced with the a nice HTML dump shown above: - - $query=new CGI; - print "<h2>Current Values</h2> $query\n"; - -=head1 FETCHING ENVIRONMENT VARIABLES - -Some of the more useful environment variables can be fetched -through this interface. The methods are as follows: - -=over 4 - -=item B<Accept()> - -Return a list of MIME types that the remote browser accepts. If you -give this method a single argument corresponding to a MIME type, as in -Accept('text/html'), it will return a floating point value -corresponding to the browser's preference for this type from 0.0 -(don't want) to 1.0. Glob types (e.g. text/*) in the browser's accept -list are handled correctly. - -Note that the capitalization changed between version 2.43 and 2.44 in -order to avoid conflict with Perl's accept() function. - -=item B<raw_cookie()> - -Returns the HTTP_COOKIE variable. Cookies have a special format, and -this method call just returns the raw form (?cookie dough). See -cookie() for ways of setting and retrieving cooked cookies. - -Called with no parameters, raw_cookie() returns the packed cookie -structure. You can separate it into individual cookies by splitting -on the character sequence "; ". Called with the name of a cookie, -retrieves the B<unescaped> form of the cookie. You can use the -regular cookie() method to get the names, or use the raw_fetch() -method from the CGI::Cookie module. - -=item B<user_agent()> - -Returns the HTTP_USER_AGENT variable. If you give -this method a single argument, it will attempt to -pattern match on it, allowing you to do something -like user_agent(Mozilla); - -=item B<path_info()> - -Returns additional path information from the script URL. -E.G. fetching /cgi-bin/your_script/additional/stuff will result in -path_info() returning "/additional/stuff". - -NOTE: The Microsoft Internet Information Server -is broken with respect to additional path information. If -you use the Perl DLL library, the IIS server will attempt to -execute the additional path information as a Perl script. -If you use the ordinary file associations mapping, the -path information will be present in the environment, -but incorrect. The best thing to do is to avoid using additional -path information in CGI scripts destined for use with IIS. - -=item B<path_translated()> - -As per path_info() but returns the additional -path information translated into a physical path, e.g. -"/usr/local/etc/httpd/htdocs/additional/stuff". - -The Microsoft IIS is broken with respect to the translated -path as well. - -=item B<remote_host()> - -Returns either the remote host name or IP address. -if the former is unavailable. - -=item B<script_name()> -Return the script name as a partial URL, for self-refering -scripts. - -=item B<referer()> - -Return the URL of the page the browser was viewing -prior to fetching your script. Not available for all -browsers. - -=item B<auth_type ()> - -Return the authorization/verification method in use for this -script, if any. - -=item B<server_name ()> - -Returns the name of the server, usually the machine's host -name. - -=item B<virtual_host ()> - -When using virtual hosts, returns the name of the host that -the browser attempted to contact - -=item B<server_port ()> - -Return the port that the server is listening on. - -=item B<virtual_port ()> - -Like server_port() except that it takes virtual hosts into account. -Use this when running with virtual hosts. - -=item B<server_software ()> - -Returns the server software and version number. - -=item B<remote_user ()> - -Return the authorization/verification name used for user -verification, if this script is protected. - -=item B<user_name ()> - -Attempt to obtain the remote user's name, using a variety of different -techniques. This only works with older browsers such as Mosaic. -Newer browsers do not report the user name for privacy reasons! - -=item B<request_method()> - -Returns the method used to access your script, usually -one of 'POST', 'GET' or 'HEAD'. - -=item B<content_type()> - -Returns the content_type of data submitted in a POST, generally -multipart/form-data or application/x-www-form-urlencoded - -=item B<http()> - -Called with no arguments returns the list of HTTP environment -variables, including such things as HTTP_USER_AGENT, -HTTP_ACCEPT_LANGUAGE, and HTTP_ACCEPT_CHARSET, corresponding to the -like-named HTTP header fields in the request. Called with the name of -an HTTP header field, returns its value. Capitalization and the use -of hyphens versus underscores are not significant. - -For example, all three of these examples are equivalent: - - $requested_language = http('Accept-language'); - $requested_language = http('Accept_language'); - $requested_language = http('HTTP_ACCEPT_LANGUAGE'); - -=item B<https()> - -The same as I<http()>, but operates on the HTTPS environment variables -present when the SSL protocol is in effect. Can be used to determine -whether SSL is turned on. - -=back - -=head1 USING NPH SCRIPTS - -NPH, or "no-parsed-header", scripts bypass the server completely by -sending the complete HTTP header directly to the browser. This has -slight performance benefits, but is of most use for taking advantage -of HTTP extensions that are not directly supported by your server, -such as server push and PICS headers. - -Servers use a variety of conventions for designating CGI scripts as -NPH. Many Unix servers look at the beginning of the script's name for -the prefix "nph-". The Macintosh WebSTAR server and Microsoft's -Internet Information Server, in contrast, try to decide whether a -program is an NPH script by examining the first line of script output. - - -CGI.pm supports NPH scripts with a special NPH mode. When in this -mode, CGI.pm will output the necessary extra header information when -the header() and redirect() methods are -called. - -The Microsoft Internet Information Server requires NPH mode. As of -version 2.30, CGI.pm will automatically detect when the script is -running under IIS and put itself into this mode. You do not need to -do this manually, although it won't hurt anything if you do. However, -note that if you have applied Service Pack 6, much of the -functionality of NPH scripts, including the ability to redirect while -setting a cookie, b<do not work at all> on IIS without a special patch -from Microsoft. See -http://support.microsoft.com/support/kb/articles/Q280/3/41.ASP: -Non-Parsed Headers Stripped From CGI Applications That Have nph- -Prefix in Name. - -=over 4 - -=item In the B<use> statement - -Simply add the "-nph" pragmato the list of symbols to be imported into -your script: - - use CGI qw(:standard -nph) - -=item By calling the B<nph()> method: - -Call B<nph()> with a non-zero parameter at any point after using CGI.pm in your program. - - CGI->nph(1) - -=item By using B<-nph> parameters - -in the B<header()> and B<redirect()> statements: - - print header(-nph=>1); - -=back - -=head1 Server Push - -CGI.pm provides four simple functions for producing multipart -documents of the type needed to implement server push. These -functions were graciously provided by Ed Jordan <ed@fidalgo.net>. To -import these into your namespace, you must import the ":push" set. -You are also advised to put the script into NPH mode and to set $| to -1 to avoid buffering problems. - -Here is a simple script that demonstrates server push: - - #!/usr/local/bin/perl - use CGI qw/:push -nph/; - $| = 1; - print multipart_init(-boundary=>'----here we go!'); - for (0 .. 4) { - print multipart_start(-type=>'text/plain'), - "The current time is ",scalar(localtime),"\n"; - if ($_ < 4) { - print multipart_end; - } else { - print multipart_final; - } - sleep 1; - } - -This script initializes server push by calling B<multipart_init()>. -It then enters a loop in which it begins a new multipart section by -calling B<multipart_start()>, prints the current local time, -and ends a multipart section with B<multipart_end()>. It then sleeps -a second, and begins again. On the final iteration, it ends the -multipart section with B<multipart_final()> rather than with -B<multipart_end()>. - -=over 4 - -=item multipart_init() - - multipart_init(-boundary=>$boundary); - -Initialize the multipart system. The -boundary argument specifies -what MIME boundary string to use to separate parts of the document. -If not provided, CGI.pm chooses a reasonable boundary for you. - -=item multipart_start() - - multipart_start(-type=>$type) - -Start a new part of the multipart document using the specified MIME -type. If not specified, text/html is assumed. - -=item multipart_end() - - multipart_end() - -End a part. You must remember to call multipart_end() once for each -multipart_start(), except at the end of the last part of the multipart -document when multipart_final() should be called instead of multipart_end(). - -=item multipart_final() - - multipart_final() - -End all parts. You should call multipart_final() rather than -multipart_end() at the end of the last part of the multipart document. - -=back - -Users interested in server push applications should also have a look -at the CGI::Push module. - -=head1 Avoiding Denial of Service Attacks - -A potential problem with CGI.pm is that, by default, it attempts to -process form POSTings no matter how large they are. A wily hacker -could attack your site by sending a CGI script a huge POST of many -megabytes. CGI.pm will attempt to read the entire POST into a -variable, growing hugely in size until it runs out of memory. While -the script attempts to allocate the memory the system may slow down -dramatically. This is a form of denial of service attack. - -Another possible attack is for the remote user to force CGI.pm to -accept a huge file upload. CGI.pm will accept the upload and store it -in a temporary directory even if your script doesn't expect to receive -an uploaded file. CGI.pm will delete the file automatically when it -terminates, but in the meantime the remote user may have filled up the -server's disk space, causing problems for other programs. - -The best way to avoid denial of service attacks is to limit the amount -of memory, CPU time and disk space that CGI scripts can use. Some Web -servers come with built-in facilities to accomplish this. In other -cases, you can use the shell I<limit> or I<ulimit> -commands to put ceilings on CGI resource usage. - - -CGI.pm also has some simple built-in protections against denial of -service attacks, but you must activate them before you can use them. -These take the form of two global variables in the CGI name space: - -=over 4 - -=item B<$CGI::POST_MAX> - -If set to a non-negative integer, this variable puts a ceiling -on the size of POSTings, in bytes. If CGI.pm detects a POST -that is greater than the ceiling, it will immediately exit with an error -message. This value will affect both ordinary POSTs and -multipart POSTs, meaning that it limits the maximum size of file -uploads as well. You should set this to a reasonably high -value, such as 1 megabyte. - -=item B<$CGI::DISABLE_UPLOADS> - -If set to a non-zero value, this will disable file uploads -completely. Other fill-out form values will work as usual. - -=back - -You can use these variables in either of two ways. - -=over 4 - -=item B<1. On a script-by-script basis> - -Set the variable at the top of the script, right after the "use" statement: - - use CGI qw/:standard/; - use CGI::Carp 'fatalsToBrowser'; - $CGI::POST_MAX=1024 * 100; # max 100K posts - $CGI::DISABLE_UPLOADS = 1; # no uploads - -=item B<2. Globally for all scripts> - -Open up CGI.pm, find the definitions for $POST_MAX and -$DISABLE_UPLOADS, and set them to the desired values. You'll -find them towards the top of the file in a subroutine named -initialize_globals(). - -=back - -An attempt to send a POST larger than $POST_MAX bytes will cause -I<param()> to return an empty CGI parameter list. You can test for -this event by checking I<cgi_error()>, either after you create the CGI -object or, if you are using the function-oriented interface, call -<param()> for the first time. If the POST was intercepted, then -cgi_error() will return the message "413 POST too large". - -This error message is actually defined by the HTTP protocol, and is -designed to be returned to the browser as the CGI script's status - code. For example: - - $uploaded_file = param('upload'); - if (!$uploaded_file && cgi_error()) { - print header(-status=>cgi_error()); - exit 0; - } - -However it isn't clear that any browser currently knows what to do -with this status code. It might be better just to create an -HTML page that warns the user of the problem. - -=head1 COMPATIBILITY WITH CGI-LIB.PL - -To make it easier to port existing programs that use cgi-lib.pl the -compatibility routine "ReadParse" is provided. Porting is simple: - -OLD VERSION - require "cgi-lib.pl"; - &ReadParse; - print "The value of the antique is $in{antique}.\n"; - -NEW VERSION - use CGI; - CGI::ReadParse(); - print "The value of the antique is $in{antique}.\n"; - -CGI.pm's ReadParse() routine creates a tied variable named %in, -which can be accessed to obtain the query variables. Like -ReadParse, you can also provide your own variable. Infrequently -used features of ReadParse, such as the creation of @in and $in -variables, are not supported. - -Once you use ReadParse, you can retrieve the query object itself -this way: - - $q = $in{CGI}; - print textfield(-name=>'wow', - -value=>'does this really work?'); - -This allows you to start using the more interesting features -of CGI.pm without rewriting your old scripts from scratch. - -=head1 AUTHOR INFORMATION - -The CGI.pm distribution is copyright 1995-2007, Lincoln D. Stein. It is -distributed under GPL and the Artistic License 2.0. - -Address bug reports and comments to: lstein@cshl.org. When sending -bug reports, please provide the version of CGI.pm, the version of -Perl, the name and version of your Web server, and the name and -version of the operating system you are using. If the problem is even -remotely browser dependent, please provide information about the -affected browers as well. - -=head1 CREDITS - -Thanks very much to: - -=over 4 - -=item Matt Heffron (heffron@falstaff.css.beckman.com) - -=item James Taylor (james.taylor@srs.gov) - -=item Scott Anguish <sanguish@digifix.com> - -=item Mike Jewell (mlj3u@virginia.edu) - -=item Timothy Shimmin (tes@kbs.citri.edu.au) - -=item Joergen Haegg (jh@axis.se) - -=item Laurent Delfosse (delfosse@delfosse.com) - -=item Richard Resnick (applepi1@aol.com) - -=item Craig Bishop (csb@barwonwater.vic.gov.au) - -=item Tony Curtis (tc@vcpc.univie.ac.at) - -=item Tim Bunce (Tim.Bunce@ig.co.uk) - -=item Tom Christiansen (tchrist@convex.com) - -=item Andreas Koenig (k@franz.ww.TU-Berlin.DE) - -=item Tim MacKenzie (Tim.MacKenzie@fulcrum.com.au) - -=item Kevin B. Hendricks (kbhend@dogwood.tyler.wm.edu) - -=item Stephen Dahmen (joyfire@inxpress.net) - -=item Ed Jordan (ed@fidalgo.net) - -=item David Alan Pisoni (david@cnation.com) - -=item Doug MacEachern (dougm@opengroup.org) - -=item Robin Houston (robin@oneworld.org) - -=item ...and many many more... - -for suggestions and bug fixes. - -=back - -=head1 A COMPLETE EXAMPLE OF A SIMPLE FORM-BASED SCRIPT - - - #!/usr/local/bin/perl - - use CGI ':standard'; - - print header; - print start_html("Example CGI.pm Form"); - print "<h1> Example CGI.pm Form</h1>\n"; - print_prompt(); - do_work(); - print_tail(); - print end_html; - - sub print_prompt { - print start_form; - print "<em>What's your name?</em><br>"; - print textfield('name'); - print checkbox('Not my real name'); - - print "<p><em>Where can you find English Sparrows?</em><br>"; - print checkbox_group( - -name=>'Sparrow locations', - -values=>[England,France,Spain,Asia,Hoboken], - -linebreak=>'yes', - -defaults=>[England,Asia]); - - print "<p><em>How far can they fly?</em><br>", - radio_group( - -name=>'how far', - -values=>['10 ft','1 mile','10 miles','real far'], - -default=>'1 mile'); - - print "<p><em>What's your favorite color?</em> "; - print popup_menu(-name=>'Color', - -values=>['black','brown','red','yellow'], - -default=>'red'); - - print hidden('Reference','Monty Python and the Holy Grail'); - - print "<p><em>What have you got there?</em><br>"; - print scrolling_list( - -name=>'possessions', - -values=>['A Coconut','A Grail','An Icon', - 'A Sword','A Ticket'], - -size=>5, - -multiple=>'true'); - - print "<p><em>Any parting comments?</em><br>"; - print textarea(-name=>'Comments', - -rows=>10, - -columns=>50); - - print "<p>",reset; - print submit('Action','Shout'); - print submit('Action','Scream'); - print end_form; - print "<hr>\n"; - } - - sub do_work { - my(@values,$key); - - print "<h2>Here are the current settings in this form</h2>"; - - for $key (param) { - print "<strong>$key</strong> -> "; - @values = param($key); - print join(", ",@values),"<br>\n"; - } - } - - sub print_tail { - print <<END; - <hr> - <address>Lincoln D. Stein</address><br> - <a href="/">Home Page</a> - END - } - -=head1 BUGS - -Please report them. - -=head1 SEE ALSO - -L<CGI::Carp>, L<CGI::Fast>, L<CGI::Pretty> - -=cut - diff --git a/ext/CGI/lib/CGI/Apache.pm b/ext/CGI/lib/CGI/Apache.pm deleted file mode 100644 index e055e30555..0000000000 --- a/ext/CGI/lib/CGI/Apache.pm +++ /dev/null @@ -1,27 +0,0 @@ -package CGI::Apache; -use CGI; - -$VERSION = '1.01'; - -1; -__END__ - -=head1 NAME - -CGI::Apache - Backward compatibility module for CGI.pm - -=head1 SYNOPSIS - -Do not use this module. It is deprecated. - -=head1 ABSTRACT - -=head1 DESCRIPTION - -=head1 AUTHOR INFORMATION - -=head1 BUGS - -=head1 SEE ALSO - -=cut diff --git a/ext/CGI/lib/CGI/Carp.pm b/ext/CGI/lib/CGI/Carp.pm deleted file mode 100644 index aa79d1921f..0000000000 --- a/ext/CGI/lib/CGI/Carp.pm +++ /dev/null @@ -1,604 +0,0 @@ -package CGI::Carp; - -=head1 NAME - -B<CGI::Carp> - CGI routines for writing to the HTTPD (or other) error log - -=head1 SYNOPSIS - - use CGI::Carp; - - croak "We're outta here!"; - confess "It was my fault: $!"; - carp "It was your fault!"; - warn "I'm confused"; - die "I'm dying.\n"; - - use CGI::Carp qw(cluck); - cluck "I wouldn't do that if I were you"; - - use CGI::Carp qw(fatalsToBrowser); - die "Fatal error messages are now sent to browser"; - -=head1 DESCRIPTION - -CGI scripts have a nasty habit of leaving warning messages in the error -logs that are neither time stamped nor fully identified. Tracking down -the script that caused the error is a pain. This fixes that. Replace -the usual - - use Carp; - -with - - use CGI::Carp - -And the standard warn(), die (), croak(), confess() and carp() calls -will automagically be replaced with functions that write out nicely -time-stamped messages to the HTTP server error log. - -For example: - - [Fri Nov 17 21:40:43 1995] test.pl: I'm confused at test.pl line 3. - [Fri Nov 17 21:40:43 1995] test.pl: Got an error message: Permission denied. - [Fri Nov 17 21:40:43 1995] test.pl: I'm dying. - -=head1 REDIRECTING ERROR MESSAGES - -By default, error messages are sent to STDERR. Most HTTPD servers -direct STDERR to the server's error log. Some applications may wish -to keep private error logs, distinct from the server's error log, or -they may wish to direct error messages to STDOUT so that the browser -will receive them. - -The C<carpout()> function is provided for this purpose. Since -carpout() is not exported by default, you must import it explicitly by -saying - - use CGI::Carp qw(carpout); - -The carpout() function requires one argument, which should be a -reference to an open filehandle for writing errors. It should be -called in a C<BEGIN> block at the top of the CGI application so that -compiler errors will be caught. Example: - - BEGIN { - use CGI::Carp qw(carpout); - open(LOG, ">>/usr/local/cgi-logs/mycgi-log") or - die("Unable to open mycgi-log: $!\n"); - carpout(LOG); - } - -carpout() does not handle file locking on the log for you at this point. - -The real STDERR is not closed -- it is moved to CGI::Carp::SAVEERR. Some -servers, when dealing with CGI scripts, close their connection to the -browser when the script closes STDOUT and STDERR. CGI::Carp::SAVEERR is there to -prevent this from happening prematurely. - -You can pass filehandles to carpout() in a variety of ways. The "correct" -way according to Tom Christiansen is to pass a reference to a filehandle -GLOB: - - carpout(\*LOG); - -This looks weird to mere mortals however, so the following syntaxes are -accepted as well: - - carpout(LOG); - carpout(main::LOG); - carpout(main'LOG); - carpout(\LOG); - carpout(\'main::LOG'); - - ... and so on - -FileHandle and other objects work as well. - -Use of carpout() is not great for performance, so it is recommended -for debugging purposes or for moderate-use applications. A future -version of this module may delay redirecting STDERR until one of the -CGI::Carp methods is called to prevent the performance hit. - -=head1 MAKING PERL ERRORS APPEAR IN THE BROWSER WINDOW - -If you want to send fatal (die, confess) errors to the browser, ask to -import the special "fatalsToBrowser" subroutine: - - use CGI::Carp qw(fatalsToBrowser); - die "Bad error here"; - -Fatal errors will now be echoed to the browser as well as to the log. CGI::Carp -arranges to send a minimal HTTP header to the browser so that even errors that -occur in the early compile phase will be seen. -Nonfatal errors will still be directed to the log file only (unless redirected -with carpout). - -Note that fatalsToBrowser does B<not> work with mod_perl version 2.0 -and higher. - -=head2 Changing the default message - -By default, the software error message is followed by a note to -contact the Webmaster by e-mail with the time and date of the error. -If this message is not to your liking, you can change it using the -set_message() routine. This is not imported by default; you should -import it on the use() line: - - use CGI::Carp qw(fatalsToBrowser set_message); - set_message("It's not a bug, it's a feature!"); - -You may also pass in a code reference in order to create a custom -error message. At run time, your code will be called with the text -of the error message that caused the script to die. Example: - - use CGI::Carp qw(fatalsToBrowser set_message); - BEGIN { - sub handle_errors { - my $msg = shift; - print "<h1>Oh gosh</h1>"; - print "<p>Got an error: $msg</p>"; - } - set_message(\&handle_errors); - } - -In order to correctly intercept compile-time errors, you should call -set_message() from within a BEGIN{} block. - -=head1 DOING MORE THAN PRINTING A MESSAGE IN THE EVENT OF PERL ERRORS - -If fatalsToBrowser in conjunction with set_message does not provide -you with all of the functionality you need, you can go one step -further by specifying a function to be executed any time a script -calls "die", has a syntax error, or dies unexpectedly at runtime -with a line like "undef->explode();". - - use CGI::Carp qw(set_die_handler); - BEGIN { - sub handle_errors { - my $msg = shift; - print "content-type: text/html\n\n"; - print "<h1>Oh gosh</h1>"; - print "<p>Got an error: $msg</p>"; - - #proceed to send an email to a system administrator, - #write a detailed message to the browser and/or a log, - #etc.... - } - set_die_handler(\&handle_errors); - } - -Notice that if you use set_die_handler(), you must handle sending -HTML headers to the browser yourself if you are printing a message. - -If you use set_die_handler(), you will most likely interfere with -the behavior of fatalsToBrowser, so you must use this or that, not -both. - -Using set_die_handler() sets SIG{__DIE__} (as does fatalsToBrowser), -and there is only one SIG{__DIE__}. This means that if you are -attempting to set SIG{__DIE__} yourself, you may interfere with -this module's functionality, or this module may interfere with -your module's functionality. - -=head1 MAKING WARNINGS APPEAR AS HTML COMMENTS - -It is now also possible to make non-fatal errors appear as HTML -comments embedded in the output of your program. To enable this -feature, export the new "warningsToBrowser" subroutine. Since sending -warnings to the browser before the HTTP headers have been sent would -cause an error, any warnings are stored in an internal buffer until -you call the warningsToBrowser() subroutine with a true argument: - - use CGI::Carp qw(fatalsToBrowser warningsToBrowser); - use CGI qw(:standard); - print header(); - warningsToBrowser(1); - -You may also give a false argument to warningsToBrowser() to prevent -warnings from being sent to the browser while you are printing some -content where HTML comments are not allowed: - - warningsToBrowser(0); # disable warnings - print "<script type=\"text/javascript\"><!--\n"; - print_some_javascript_code(); - print "//--></script>\n"; - warningsToBrowser(1); # re-enable warnings - -Note: In this respect warningsToBrowser() differs fundamentally from -fatalsToBrowser(), which you should never call yourself! - -=head1 OVERRIDING THE NAME OF THE PROGRAM - -CGI::Carp includes the name of the program that generated the error or -warning in the messages written to the log and the browser window. -Sometimes, Perl can get confused about what the actual name of the -executed program was. In these cases, you can override the program -name that CGI::Carp will use for all messages. - -The quick way to do that is to tell CGI::Carp the name of the program -in its use statement. You can do that by adding -"name=cgi_carp_log_name" to your "use" statement. For example: - - use CGI::Carp qw(name=cgi_carp_log_name); - -. If you want to change the program name partway through the program, -you can use the C<set_progname()> function instead. It is not -exported by default, you must import it explicitly by saying - - use CGI::Carp qw(set_progname); - -Once you've done that, you can change the logged name of the program -at any time by calling - - set_progname(new_program_name); - -You can set the program back to the default by calling - - set_progname(undef); - -Note that this override doesn't happen until after the program has -compiled, so any compile-time errors will still show up with the -non-overridden program name - -=head1 CHANGE LOG - -1.29 Patch from Peter Whaite to fix the unfixable problem of CGI::Carp - not behaving correctly in an eval() context. - -1.05 carpout() added and minor corrections by Marc Hedlund - <hedlund@best.com> on 11/26/95. - -1.06 fatalsToBrowser() no longer aborts for fatal errors within - eval() statements. - -1.08 set_message() added and carpout() expanded to allow for FileHandle - objects. - -1.09 set_message() now allows users to pass a code REFERENCE for - really custom error messages. croak and carp are now - exported by default. Thanks to Gunther Birznieks for the - patches. - -1.10 Patch from Chris Dean (ctdean@cogit.com) to allow - module to run correctly under mod_perl. - -1.11 Changed order of > and < escapes. - -1.12 Changed die() on line 217 to CORE::die to avoid B<-w> warning. - -1.13 Added cluck() to make the module orthogonal with Carp. - More mod_perl related fixes. - -1.20 Patch from Ilmari Karonen (perl@itz.pp.sci.fi): Added - warningsToBrowser(). Replaced <CODE> tags with <PRE> in - fatalsToBrowser() output. - -1.23 ineval() now checks both $^S and inspects the message for the "eval" pattern - (hack alert!) in order to accommodate various combinations of Perl and - mod_perl. - -1.24 Patch from Scott Gifford (sgifford@suspectclass.com): Add support - for overriding program name. - -1.26 Replaced CORE::GLOBAL::die with the evil $SIG{__DIE__} because the - former isn't working in some people's hands. There is no such thing - as reliable exception handling in Perl. - -1.27 Replaced tell STDOUT with bytes=tell STDOUT. - -=head1 AUTHORS - -Copyright 1995-2002, Lincoln D. Stein. All rights reserved. - -This library is free software; you can redistribute it and/or modify -it under the same terms as Perl itself. - -Address bug reports and comments to: lstein@cshl.org - -=head1 SEE ALSO - -Carp, CGI::Base, CGI::BasePlus, CGI::Request, CGI::MiniSvr, CGI::Form, -CGI::Response - -=cut - -require 5.000; -use Exporter; -#use Carp; -BEGIN { - require Carp; - *CORE::GLOBAL::die = \&CGI::Carp::die; -} - -use File::Spec; - -@ISA = qw(Exporter); -@EXPORT = qw(confess croak carp); -@EXPORT_OK = qw(carpout fatalsToBrowser warningsToBrowser wrap set_message set_die_handler set_progname cluck ^name= die); - -$main::SIG{__WARN__}=\&CGI::Carp::warn; - -$CGI::Carp::VERSION = '3.45'; -$CGI::Carp::CUSTOM_MSG = undef; -$CGI::Carp::DIE_HANDLER = undef; - - -# fancy import routine detects and handles 'errorWrap' specially. -sub import { - my $pkg = shift; - my(%routines); - my(@name); - if (@name=grep(/^name=/,@_)) - { - my($n) = (split(/=/,$name[0]))[1]; - set_progname($n); - @_=grep(!/^name=/,@_); - } - - grep($routines{$_}++,@_,@EXPORT); - $WRAP++ if $routines{'fatalsToBrowser'} || $routines{'wrap'}; - $WARN++ if $routines{'warningsToBrowser'}; - my($oldlevel) = $Exporter::ExportLevel; - $Exporter::ExportLevel = 1; - Exporter::import($pkg,keys %routines); - $Exporter::ExportLevel = $oldlevel; - $main::SIG{__DIE__} =\&CGI::Carp::die if $routines{'fatalsToBrowser'}; -# $pkg->export('CORE::GLOBAL','die'); -} - -# These are the originals -sub realwarn { CORE::warn(@_); } -sub realdie { CORE::die(@_); } - -sub id { - my $level = shift; - my($pack,$file,$line,$sub) = caller($level); - my($dev,$dirs,$id) = File::Spec->splitpath($file); - return ($file,$line,$id); -} - -sub stamp { - my $time = scalar(localtime); - my $frame = 0; - my ($id,$pack,$file,$dev,$dirs); - if (defined($CGI::Carp::PROGNAME)) { - $id = $CGI::Carp::PROGNAME; - } else { - do { - $id = $file; - ($pack,$file) = caller($frame++); - } until !$file; - } - ($dev,$dirs,$id) = File::Spec->splitpath($id); - return "[$time] $id: "; -} - -sub set_progname { - $CGI::Carp::PROGNAME = shift; - return $CGI::Carp::PROGNAME; -} - - -sub warn { - my $message = shift; - my($file,$line,$id) = id(1); - $message .= " at $file line $line.\n" unless $message=~/\n$/; - _warn($message) if $WARN; - my $stamp = stamp; - $message=~s/^/$stamp/gm; - realwarn $message; -} - -sub _warn { - my $msg = shift; - if ($EMIT_WARNINGS) { - # We need to mangle the message a bit to make it a valid HTML - # comment. This is done by substituting similar-looking ISO - # 8859-1 characters for <, > and -. This is a hack. - $msg =~ tr/<>-/\253\273\255/; - chomp $msg; - print STDOUT "<!-- warning: $msg -->\n"; - } else { - push @WARNINGS, $msg; - } -} - - -# The mod_perl package Apache::Registry loads CGI programs by calling -# eval. These evals don't count when looking at the stack backtrace. -sub _longmess { - my $message = Carp::longmess(); - $message =~ s,eval[^\n]+(ModPerl|Apache)/(?:Registry|Dispatch)\w*\.pm.*,,s - if exists $ENV{MOD_PERL}; - return $message; -} - -sub ineval { - (exists $ENV{MOD_PERL} ? 0 : $^S) || _longmess() =~ /eval [\{\']/m -} - -sub die { - my ($arg,@rest) = @_; - - if ($DIE_HANDLER) { - &$DIE_HANDLER($arg,@rest); - } - - if ( ineval() ) { - if (!ref($arg)) { - $arg = join("",($arg,@rest)) || "Died"; - my($file,$line,$id) = id(1); - $arg .= " at $file line $line.\n" unless $arg=~/\n$/; - realdie($arg); - } - else { - realdie($arg,@rest); - } - } - - if (!ref($arg)) { - $arg = join("", ($arg,@rest)); - my($file,$line,$id) = id(1); - $arg .= " at $file line $line." unless $arg=~/\n$/; - &fatalsToBrowser($arg) if $WRAP; - if (($arg =~ /\n$/) || !exists($ENV{MOD_PERL})) { - my $stamp = stamp; - $arg=~s/^/$stamp/gm; - } - if ($arg !~ /\n$/) { - $arg .= "\n"; - } - } - realdie $arg; -} - -sub set_message { - $CGI::Carp::CUSTOM_MSG = shift; - return $CGI::Carp::CUSTOM_MSG; -} - -sub set_die_handler { - - my ($handler) = shift; - - #setting SIG{__DIE__} here is necessary to catch runtime - #errors which are not called by literally saying "die", - #such as the line "undef->explode();". however, doing this - #will interfere with fatalsToBrowser, which also sets - #SIG{__DIE__} in the import() function above (or the - #import() function above may interfere with this). for - #this reason, you should choose to either set the die - #handler here, or use fatalsToBrowser, not both. - $main::SIG{__DIE__} = $handler; - - $CGI::Carp::DIE_HANDLER = $handler; - - return $CGI::Carp::DIE_HANDLER; -} - -sub confess { CGI::Carp::die Carp::longmess @_; } -sub croak { CGI::Carp::die Carp::shortmess @_; } -sub carp { CGI::Carp::warn Carp::shortmess @_; } -sub cluck { CGI::Carp::warn Carp::longmess @_; } - -# We have to be ready to accept a filehandle as a reference -# or a string. -sub carpout { - my($in) = @_; - my($no) = fileno(to_filehandle($in)); - realdie("Invalid filehandle $in\n") unless defined $no; - - open(SAVEERR, ">&STDERR"); - open(STDERR, ">&$no") or - ( print SAVEERR "Unable to redirect STDERR: $!\n" and exit(1) ); -} - -sub warningsToBrowser { - $EMIT_WARNINGS = @_ ? shift : 1; - _warn(shift @WARNINGS) while $EMIT_WARNINGS and @WARNINGS; -} - -# headers -sub fatalsToBrowser { - my($msg) = @_; - $msg=~s/&/&/g; - $msg=~s/>/>/g; - $msg=~s/</</g; - $msg=~s/\"/"/g; - my($wm) = $ENV{SERVER_ADMIN} ? - qq[the webmaster (<a href="mailto:$ENV{SERVER_ADMIN}">$ENV{SERVER_ADMIN}</a>)] : - "this site's webmaster"; - my ($outer_message) = <<END; -For help, please send mail to $wm, giving this error message -and the time and date of the error. -END - ; - my $mod_perl = exists $ENV{MOD_PERL}; - - if ($CUSTOM_MSG) { - if (ref($CUSTOM_MSG) eq 'CODE') { - print STDOUT "Content-type: text/html\n\n" - unless $mod_perl; - eval { - &$CUSTOM_MSG($msg); # nicer to perl 5.003 users - }; - if ($@) { print STDERR q(error while executing the error handler: $@); } - - return; - } else { - $outer_message = $CUSTOM_MSG; - } - } - - my $mess = <<END; -<h1>Software error:</h1> -<pre>$msg</pre> -<p> -$outer_message -</p> -END - ; - - if ($mod_perl) { - my $r; - if ($ENV{MOD_PERL_API_VERSION} && $ENV{MOD_PERL_API_VERSION} == 2) { - $mod_perl = 2; - require Apache2::RequestRec; - require Apache2::RequestIO; - require Apache2::RequestUtil; - require APR::Pool; - require ModPerl::Util; - require Apache2::Response; - $r = Apache2::RequestUtil->request; - } - else { - $r = Apache->request; - } - # If bytes have already been sent, then - # we print the message out directly. - # Otherwise we make a custom error - # handler to produce the doc for us. - if ($r->bytes_sent) { - $r->print($mess); - $mod_perl == 2 ? ModPerl::Util::exit(0) : $r->exit; - } else { - # MSIE won't display a custom 500 response unless it is >512 bytes! - if ($ENV{HTTP_USER_AGENT} =~ /MSIE/) { - $mess = "<!-- " . (' ' x 513) . " -->\n$mess"; - } - $r->custom_response(500,$mess); - } - } else { - my $bytes_written = eval{tell STDOUT}; - if (defined $bytes_written && $bytes_written > 0) { - print STDOUT $mess; - } - else { - print STDOUT "Status: 500\n"; - print STDOUT "Content-type: text/html\n\n"; - print STDOUT $mess; - } - } - - warningsToBrowser(1); # emit warnings before dying -} - -# Cut and paste from CGI.pm so that we don't have the overhead of -# always loading the entire CGI module. -sub to_filehandle { - my $thingy = shift; - return undef unless $thingy; - return $thingy if UNIVERSAL::isa($thingy,'GLOB'); - return $thingy if UNIVERSAL::isa($thingy,'FileHandle'); - if (!ref($thingy)) { - my $caller = 1; - while (my $package = caller($caller++)) { - my($tmp) = $thingy=~/[\':]/ ? $thingy : "$package\:\:$thingy"; - return $tmp if defined(fileno($tmp)); - } - } - return undef; -} - -1; diff --git a/ext/CGI/lib/CGI/Changes b/ext/CGI/lib/CGI/Changes deleted file mode 100644 index a45e39bf10..0000000000 --- a/ext/CGI/lib/CGI/Changes +++ /dev/null @@ -1,1423 +0,0 @@ -Version 3.45 - [BUG FIXES] - 1. Prevent warnings about "uninitialized values" for REQUEST_URI, HTTP_USER_AGENT and other environment variables. - Patches by Callum Gibson, heiko and Mark Stosberg. (RT#24684, RT#29065) - 2. Avoid death in some cases when running under Taint mode on Windows. - Patch by Peter Hancock (RT#43796) - 3. Allow 0 to be used as a default value in popup_menu(). This was broken starting in 3.37. - Thanks to Haze, who was the first to report this and supply a patch, and pfschill, who pinpointed - when the bug was introduced. A regression test for this was also added. (RT#37908) - 4. Allow "+" as a valid character in file names, which fixes temp file creation on OS X Leopard. - Thanks to Andy Armstrong, and alech for patches. (RT#30504) - 5. Set binmode() on the Netware platform, thanks to Guenter Knauf (RT#27455) - 6. Don't allow a CGI::Carp error handler to die recursively. Print a warning and exit instead. - Thanks to Marc Chantreux. (RT#45956) - 7. The Dump() method now is fixed to escape HTML properly. Thanks to Mark Stosberg (RT#21341) - 8. Support for <optgroup> with scrolling_list() now works the same way as it does for popup_menu(). - Thanks to Stuart Johnston (RT#30097) - 9. CGI::Pretty now works properly when $" is set to ''. Thanks to Jim Keenan (RT#12401) - 10. Fix crash when used in combination with PerlEx::DBI. Thanks to Burak Gürsoy (RT#19902) - - [DOCUMENTATION] - 1. Several typos were fixed, Thanks to ambs. (RT#41105) - 2. A typo related to the nosticky pragma was fixed, thanks to Britton Kerin. (RT#43220) - 3. examples/nph-clock.cgi is now more portable, by calling localtime() rather than `/bin/date`, - thanks to Guenter Knauf. (RT#27456). - 4. In CGI::Carp, the SEE ALSO section was cleaned up, thanks to Slaven Rezic. (RT#32769) - 5. The docs for redirect() were updated to reflect that most headers are - ignored during redirection. Thanks to Mark Stosberg (RT#44911) - - [INTERNALS] - 1. New t/unescapeHTML.t test script has been added. It includes a TODO test for a pre-existing - bug which could use a patch. Thanks to Pete Gamache and Mark Stosberg (RT#39122) - 2. New test scripts have been added for user_agent(), popup_menu() and query_string(), scrolling_list() and Dump() - Thanks to Mark Stosberg and Stuart Johnston. (RT#37908, RT#43006, RT#21341, RT#30097) - 3. CGI::Carp and CGI::Util have been updated to have non-developer version numbers. - Thanks to Slaven Rezic. (RT#48425) - 4. CGI::Switch and CGI::Apache now properly set their VERSION in their own name space. - Thanks to Alexey Tourbin (RT#11941,RT#11942) - - Version 3.44 - 1. Patch from Kurt Jaeger to allow HTTP PUT even if the content length is unknown. - 2. Patch from Pavel merdin to fix a problem for one of the FireFox addons. - 3. Fixed issue in mod_perl & fastCGI environment of cookies returned from - CGI->cookie() leaking from one session to another. - - Version 3.43 - 1. Documentation patch from MARKSTOS@cpan.org to replace all occurrences of - "new CGI" with CGI->new()" to reflect best perl practices. - 2. Patch from Stepan Kasal to fix utf-8 related problems in perl 5.10 - - Version 3.42 - 1. Added patch from Renee Baecker that makes it possible to subclass - CGI::Pretty. - 2. Added patch from Nicholas Clark to allow ~ characters in temporary directories. - 3. Added patch from Renee Baecker that fixes the inappropriate escaping of fields - in multipart headers. - - Version 3.41 - 1. Fix url() returning incorrect path when query string contains escaped newline. - 2. Added additional windows temporary directories and environment variables, courtesy patch from Renee Baecker - 3. Added a handle() method to the lightweight upload - filehandles. This method returns a real IO::Handle object. - 4. Added patch from Tony Vanlingen to fix deep recursion warnings in CGI::Pretty. - - Version 3.40 - 1. Fixed CGI::Fast docs to eliminate references to a "special" - version of Perl. - 2. Makefile.PL now depends on FCGI so that CGI::Fast installs properly. - 3. Fix script_name() call from Stephane Chazelas. - - Version 3.39 - 1. Fixed regression in "exists" function when using tied interface to CGI via $q->Vars. - - Version 3.38 - 1. Fix annoying warning in http://rt.cpan.org/Ticket/Display.html?id=34551 - 2. Added nobr() function http://rt.cpan.org/Ticket/Display.html?id=35377 - 3. popup_menu() allows multiple items to be selected by default, satisfying - http://rt.cpan.org/Ticket/Display.html?id=35376 - 4. Patch from Renee Backer to avoid doubled <http-equiv> headers. - 5. Fixed documentation bug that describes what happens when a - parameter is empty (e.g. "?test1="). - 6. Fixed minor warning described at http://rt.cpan.org/Public/Bug/Display.html?id=36435 - 7. Fixed overlap of attribute and parameter space described in http://rt.perl.org/rt3//Ticket/Display.html?id=24294 - - Version 3.37 - 1. Fix pragmas so that they persist over modperl invocations (e.g. RT 34761) - 2. Fixed handling of chunked multipart uploads; thanks to Michael Bernhardt - who reported and fixed the problem. - - Version 3.36 - 1. Fix CGI::Cookie to support cookies that are separated by "," instead of ";". - - Version 3.35 - 1. Resync with bleadperl, primarily fixing a bug in parsing semicolons in uploaded filenames. - - Version 3.34 - 1. Handle Unicode %uXXXX escapes properly -- patch from DANKOGAI@cpan.org - 2. Fix url() method to not choke on path names that contain regex characters. - - Version 3.33 - 1. Remove uninit variable warning when calling url(-relative=>1) - 2. Fix uninit variable warnings for two lc calls - 3. Fixed failure of tempfile upload due to sprintf() taint failure in perl 5.10 - - Version 3.32 - 1. Patch from Miguel Santinho to prevent sending premature headers under mod_perl 2.0 - - Version 3.31 - 1. Patch from Xavier Robin so that CGI::Carp issues a 500 Status code rather than a 200 status code. - 2. Patch from Alexander Klink to select correct temporary directory in OSX Leopard so that upload works. - 3. Possibly fixed "wrapped pack" error on 5.10 and higher. - - Version 3.30 - 1. Patch from Mike Barry to handle POSTDATA in the same way as PUT. - 2. Patch from Rafael Garcia-Suarez to correctly reencode unicode values as byte values. - - Version 3.29 - 1. The position of file handles is now reset to zero when CGI->new is called. - (Mark Stosberg) - 2. uploadInfo() now works across multiple object instances. Also, the first - tests for uploadInfo() were added as part of the fix. (CPAN bug 11895, with - contributions from drfrench and Mark Stosberg). - - Version 3.28 - 1. Applied patch from Allen Day that makes Cookie parsing RFC2109 compliant - (attribute/values can be separated by commas as well as semicolons). - 2. Applied patch from Stephan Struckmann that allows script_name() to be set correctly. - 3. Fixed problem with url(-full) in which port number appears twice. - - Version 3.27 - 1. Applied patch from Steve Taylor that allows checkbox_groups to be - disabled with a new -disabled=> option. - - Version 3.26 - 1. Fixed alternate stylesheet behavior so that it is insensitive to order of declarations. - 2. Patch from John Binns to allow users to provide a callback to CGI::Carp. - 3. Added "~" as an unreserved character in escape(). - 4. Patch from Chris Fedde to prevent HTTP_HOST from inhibiting SERVER_PORT in url() generation. - 5. Fixed outdated documentation (and behavior) of -language in start_html -script option. - 6. Fixed bug in seconds calculation in CGI::Util::expire_calc. - - Version 3.25 - 1. Fixed the link to the Netscape frames page. - 2. Added ability to specify an alternate stylesheet. - 3. Add support for XForms POST submssion both as application/xml or as multipart/related - - Version 3.24 - 1. In startform(), if request_uri() returns undef, then falls back - to self_url(). This should rarely happen except when run outside of - the CGI environment. - 2. image button alignment options were mistakenly being capitalized, causing xhtml validation to fail. - - Version 3.23 - 1. Typo in upload() persisted, now fixed for real. Thanks to - Emanuele Zeppieri for correct patch and regression test. - - Version 3.22 - 1. Typo in upload() function broke uploads. Now fixed (CPAN bug 21126). - - Version 3.21 - 1. Don't try to read data at all when POST > $POST_MAX. - 2. Fixed bug that caused $cgi->param('name',undef,'value') to unset param('name') entirely. - 3. Fixed bug in which upload() sometimes returns empty. (CPAN bug #12694). - 4. Incorporated patch from BURAK@cpan.org to support HTTPcookies (CPAN bug 21019). - - Version 3.20 - 1. Patch from David Wheeler for CGI::Cookie->bake(). Uses mod_perl headers_out->add() - rather than headers_out->set(). - 2. Fixed problem identified by Andrei Voronkov in which start_form() output was screwed - up when initial argument begins with a dash and subsequent arguments do not. - 3. Quashed uninitialized variable warnings coming from script_name(), url() and other - functions that require access to the PATH_INFO environment variable. - - Version 3.19 - 1. Added patch from Stephen Frost that allows one to suppress use of the temp file that is - created during uploads. - 2. Fixed problem noted by Martin Foster in which regular expression meta-character terms - in the path information were not quoted, causing URL parsing - to fail on URLs that contained metacharacters (such as +). - 3. More fixes to the url() method. - 4. Removed "hack to fix broken PATH_INFO in MSII". - - Version 3.18 - 1. Doc typo fixes. - 2. Patch from Steve Peters to default the document type to match the charset. - 3. Fixed param() so that param(-name=>'foo',-values=>[]) sets the parameter to empty list. - - Version 3.17 Fri Feb 24 14:01:27 EST 2006 - 1. Added patch from Mike Hanafey which caused 0 arguments to CGI::Cookie->new() to - be treated as empty. - 2. Patch to CGI::Carp from Peter Whaite to fix the unfixable problem of CGI::Carp - not behaving correctly in an eval() context. - 3. CGI::Fast->new() calls CGI->_reset_globals to avoid contamination of one session - with another's variables. - 4. Fixed upload failure on files that contain semicolons in their names. - - Version 3.16 Wed Feb 8 13:29:11 EST 2006 - 1. header() -charset option now works even when the MIME type is not "text". - 2. Fixed documentation for cookie() function and fastCGI. - 3. Upload filehandles now only closed automatically on Windows systems. - 4. Apache::Cookie compatibility fix from David Wheeler - 5. CGI::Carp->fatalsToBrowser() does not work correctly with - mod_perl 2. No workaround is known. - 6. Fixed text status code associated with 302 redirects. Should be "Found" - but was "Moved". - 7. Fixed charset in start_html() and header() to be in synch. - - Version 3.15 Wed Dec 7 15:13:22 EST 2005 - 1. Remove extraneous "?" from self_url() when URI contains a ? but no query string. - - Version 3.14 Tue Dec 6 17:12:03 EST 2005 - 1. Fixed broken scrolling_list() select attribute. - - Version 3.13 - 1. Removed extraneous empty "?" from end of self_url(). - - Version 3.12 - 1. Fixed virtual_port so that it works properly with https protocol. - 2. Fixed documentation for upload_hook(). - 3. Added POSTDATA documentation. - 4. Made upload_hook() work in function-oriented mode. - 5. Fixed POST_MAX behavior so that it doesn't cause client to hang. - 6. Disabled automatic tab indexes and added new -tabindex pragma to - turn automatic indexes back on. - 7. The url() and self_url() methods now work better in the context of Apache - mod_rewrite. Be advised that path_info() may give you confusing results - when mod_rewrite is active because Apache calculates the path info *after* - rewriting. This is mostly worked around in url() and self_url(), but you - may notice some anomalies. - 8. Removed empty (and non-validating) <div> from code emitted by end_form(). - 9. Fixed CGI::Carp to work correctly with Mod_perl 1.29 in an Apache 2 environment. - 10. Setting $CGI::TMPDIRECTORY should now be effective. - - Version 3.11 - 1. Killed warning in CGI::Cookie about MOD_PERL_API_VERSION - 2. Fixed append() so that it works in function mode. - 3. Workaround for a bug that appears in Apache2 versions through 2.0.54 - in which SCRIPT_NAME and PATH_INFO are incorrect if the additional path_info - contains a double slash. This workaround will handle the common case of - http://mysite.com/cgi-bin/log.cgi/http://www.some.other.site/args, but will - not handle the uncommon case of a ScriptAlias directive that adds additional - path information to the end of the translated URI. - - Version 3.10 - 1. Added Apache2::RequestIO, which is necessary for mp2 interoperability. - - Version 3.09 - 1. Fixed tabindex="0" when using CGI to create forms without a prior start_html - 2. Removed warning about non-numeric MOD_PERL_API_VERSION. - - Version 3.08 - 1. update support for mod_perl 2.0. versions prior to - mod_perl 1.999_22 (2.0.0-RC5) are no longer supported. - - Version 3.07 - 1. Fixed typo in mod_perl detection. - - Version 3.06 - - 1. Fixed bare call to script() in start_html - 2. Moved Fh::DESTROY out of autoloaded functions so as to avoid - clobbering $@ when CGI functions are executed in an eval{} - context. - 3. mod_perl 2.0 version detection patch in CGI::Cookie provided by - Allen Day. - 4. autoEscape() flag is now respected when generating extra - attributes. - 5. Tests for *tag start/end generation from Shlomi Fish. - 6. Support for can() method provided by Ron Savage. - 7. Fix for lang='' when outputting XHTML. - 8. Added support for chunked transfer encoding, as suggested by - Hakan Ardo - 9. Fixed clobbering of row and column headers in tableized radio - and checkbox groups, as reported by Nicolas Thierry-Mieg. - 10. <Label> tags are now associated with form elements, as suggested - by accessibility guidelines. - 11. The <?xml> directive produced by start_html is now turned off by - default and the charset is specified in a <meta> directive. Apparently - IE6 (and maybe some versions of Opera) were getting confused by this. - 12. Support for tab indexes. - 13. Retired the HTML docs. The POD docs are now primary documentation. - 14. CGI::Carp now correctly detects and handles Apache::Dispatch. - 15. CGI::Util::utf8_chr now correctly sets the UTF8 flag on 5.006 or - higher perls (fix courtesy Slaven Rezic). - - - Version 3.05 - - 1. Fixed uninitialized variable warning on start_form() when running - from command line. - 2. Fixed CGI::_set_attributes so that attributes with a - are handled - correctly. - 3. Fixed CGI::Carp::die() so as to avoid problems from _longmess() - clobbering @_. - 4. If HTTP_X_FORWARDED_HOST is defined (i.e. running under a proxy), - the various functions that return HOST will use that instead. - 5. Fix for undefined utf8() call in CGI::Util. - 6. Changed the call to warningsToBrowser() in - CGI::Carp::fatalsToBrowser to call only after HTTP header is sent - (thanks to Didier Lebrun for noticing). - 7. Patches from Dan Harkless to make CGI.pm validatable against HTML - 3.2. - 8. Fixed an extraneous "foo=bar" appearing when extra style - parameters passed to start_html; - 9. Fixed cross-site scripting bug in startform() pointed out by Dan - Harkless. - 10. Fixed documentation to discuss list context behavior of - form-element generators explicitly. - 11. Fixed incorrect results from end_form() when called in OO manner. - 12. Fixed query string stripping in order to handle URLs containing - escaped newlines. - 13. During server push, set NPH to 0 rather than 1. This is supposed - to fix problems with Apache. - 14. Fixed incorrect processing of multipart form fields that contain - embedded quotes. There's still the issue of how to handle ones - that contain embedded semicolons, but no one has complained (yet). - 15. Fixed documentation bug in -style argument to start_html() - 16. Added -status argument to redirect(). - - Version 3.04 - - 1. Fixed the problem with mod_perl crashing when "defaults" button - pressed. - - Version 3.03 - - 1. Fix upload hook functionality - 2. Workaround for CGI->unescape_html() - 3. Bumped version numbers in CGI::Fast and CGI::Util for 5.8.3-tobe - - Version 3.02 - - 1. Bring in Apache::Response just in case. - 2. File upload on EBCDIC systems now works. - - Version 3.01 - - 1. No fix yet for upload failures when running on EBCDIC server. - 2. Fixed uninitialized glob warnings that appeared when file - uploading under perl 5.8.2. - 3. Added patch from Schlomi Fish to allow debugging of PATH_INFO from - command line. - 4. Added patch from Steve Hay to correctly unlink tmp files under - mod_perl/windows - 5. Added upload_hook functionality from Jamie LeTaul - 6. Workarounds for mod_perl 2 IO issues. Check that file upload and - state saving still working. - 7. Added code for underreads. - 8. Fixed misleading description of redirect() and relative URLs in - the POD docs. - 9. Workaround for weird interaction of CGI::Carp with Safe module - reported by William McKee. - 10. Added patches from Ilmari Karonen to improve behavior of - CGI::Carp. - 11. Fixed documentation error in -style argument. - 12. Added virtual_port() method for finding out what port server is - listening on in a virtual-host aware fashion. - - Version 3.00 - - 1. Patch from Randal Schwartz to fix bug introduced by cross-site - scripting vulnerability "fix." - 2. Patch from JFreeman to replace UTF-8 escape constant of 0xfe with - 0xfc. Hope this is right! - - Version 2.99 - - 1. Patch from Steve Hay to fix extra Content-type: appearing on - browser screen when FatalsToBrowser invoked. - 2. Patch from Ewann Corvellec to fix cross-site scripting - vulnerability. - 3. Fixed tmpdir routine for file uploading to solve problem that - occurs under mod_perl when tmpdir is writable at startup time, but - not at session time. - - Version 2.98 - - 1. Fixed crash in Dump() function. - - Version 2.97 - - 1. Sigh. Uploaded wrong 2.96 to CPAN. - - Version 2.96 - - 1. More bugfixes to the -style argument. - - Version 2.95 - - 1. Fixed bugs in start_html(-style=>...) support introduced in 2.94. - - Version 2.94 - - 1. Removed warning from reset() method. - 2. Moved - - and tags into the :html3 group. Hope this removes undefined CGI::Area - errors. - - Changed CGI::Carp to play with mod_perl2 and to (hopefully) restore - reporting of compile-time errors. - - Fixed potential deadlock between web server and CGI.pm when aborting - a read due to POST_MAX (reported by Antti Lankila). - - Fixed issue with tag-generating function not incorporating content - when first variable undef. - - Fixed cross-site scripting bug reported by obscure. - - Fixed Dump() function to return correctly formed XHTML - bug - reported by Ralph Siemsen. - - Version 2.93 - - 1. Fixed embarassing bug in mp1 support. - - Version 2.92 - - 1. Fix to be P3P compliant submitted from MPREWITT. - 2. Added CGI->r() API for mod_perl1/mod_perl2. - 3. Fixed bug in redirect() that was corrupting cookies. - 4. Minor fix to behavior of reset() button to make it consistent with - submit() button (first time this has been changed in 9 years). - 5. Patch from Dan Kogai to handle UTF-8 correctly in 5.8 and higher. - 6. Patch from Steve Hay to make CGI::Carp's error messages appear on - MSIE browsers. - 7. Added Yair Lenga's patch for non-urlencoded postings. - 8. Added Stas Bekman's patches for mod_perl 2 compatibility. - 9. Fixed uninitialized escape behavior submitted by William Campbell. - 10. Fixed tied behavior so that you can pass arguments to tie() - 11. Fixed incorrect generation of URLs when the path_info contains + - and other odd characters. - 12. Fixed redirect(-cookies=>$cookie) problem. - 13. Fixed tag generation bug that affects -javascript passed to - start_html(). - - Version 2.91 - - 1. Attribute generation now correctly respects the value of - autoEscape(). - 2. Fixed endofrm() syntax error introduced by Ben Edgington's patch. - - Version 2.90 - - 1. Fixed bug in redirect header handling. - 2. Added P3P option to header(). - 3. Patches from Alexey Mahotkin to make CGI::Carp work correctly with - object-oriented exceptions. - 4. Removed inaccurate description of how to set multiple cookies from - CGI::Cookie pod file. - 5. Patch from Kevin Mahony to prevent running out of filehandles when - uploading lots of files. - 6. Documentation enhancement from Mark Fisher to note that the - import_names() method transforms the parameter names into valid - Perl names. - 7. Patch from Dan Harkless to suppress lang attribute in <html> tag - if specified as a null string. - 8. Patch from Ben Edgington to fix broken XHTML-transitional 1.0 - validation on endform(). - 9. Custom html header fix from Steffen Beyer (first letter correctly - upcased now) - 10. Added a -verbatim option to stylesheet generation from Michael - Dickson - 11. Faster delete() method from Neelam Gupta - 12. Fixed broken Cygwin support. - 13. Added empty charset support from Bradley Baetz - 14. Patches from Doug Perham and Kevin Mahoney to fix file upload - failures when uploaded file is a multiple of 4096. - - Version 2.89 - - 1. Fixed behavior of ACTION tag when POSTING to a URL that has a - query string. - 2. Added Patch from Michael Rommel to handle multipart/mixed uploads - from Opera - - Version 2.88 - - 1. Fixed problem with uploads being refused under Perl 5.8 when under - Taint mode. - 2. Fixed uninitialized variable warnings under Perl 5.8. - 3. Fixed CGI::Pretty regression test failures. - - Version 2.87 - - 1. Security hole patched: when processing multipart/form-data - postings, most arguments were being untainted silently. Returned - arguments are now tainted correctly. This may cause some scripts - to fail that used to work (thanks to Nick Cleaton for pointing - this out and persisting until it was fixed). - 2. Update for mod_perl 2.0. - 3. Pragmas such as -no_xhtml are now respected in mod_perl - environment. - - Version 2.86 - - 1. Fixes for broken CGI::Cookie expiration dates introduced in 2.84. - - Version 2.85 - - 1. Fix for broken autoEscape function introduced in 2.84. - - Version 2.84 - - 1. Fix for failed file uploads on Cygwin platforms. - 2. HTML escaping code now replaced 0x8b and 0x9b with unicode - references < and *#8250; - - Version 2.83 - - 1. Fixed autoEscape() documentation inconsistencies. - 2. Patch from Ville Skyttä to fix a number of XHTML inconsistencies. - 3. Added Max-Age to list of CGI::Cookie headers. - - Version 2.82 - - 1. Patch from Rudolf Troller to add attribute setting and option - groups to form fields. - 2. Patch from Simon Perreault for silent crashes when using CGI::Carp - under mod_perl. - 3. Patch from Scott Gifford allows you to set the program name for - CGI::Carp. - - Version 2.81 - - 1. Removed extraneous slash from end of stylesheet tags generated by - start_html in non-XHTML mode. - 2. Changed behavior of CGI::Carp with respect to eval{} contexts so - that output behaves properly in mod_perl environments. - 3. Fixed default DTD so that it validates with W3C validator. - - Version 2.80 - - 1. Fixed broken messages in CGI::Carp. - 2. Changed checked="1" to checked="checked" for real XHTML - compatibility. - 3. Resurrected REQUEST_URI code so that url() works correctly with - multiviews. - - Version 2.79 - - 1. Changes to CGI::Carp to avoid "subroutine redefined" error - messages. - 2. Default DTD is now XHTML 1.0 Transitional - 3. Patches to support all HTML4 tags. - - Version 2.78 - - 1. Added ability to change encoding in <?xml> assertion. - 2. Fixed the old escapeHTML('CGI') ne "CGI" bug - 3. In accordance with XHTML requirements, there are no longer any - minimized attributes, such as "checked". - 4. Patched bug which caused file uploads of exactly 4096 bytes to be - truncated to 4094 (thanks to Kevin Mahony) - 5. New tests and fixes to CGI::Pretty (thanks to Michael Schwern). - - Version 2.77 - - 1. No new features, but released in order to fix an apparent CPAN - bug. - - Version 2.76 - - 1. New esc.t regression test for EBCDIC translations courtesy Peter - Prymmer. - 2. Patches from James Jurach to make compatible with FCGI-ProcManager - 3. Additional fields passed to header() (like -Content_disposition) - now honor initial capitalization. - 4. Patch from Andrew McNaughton to handle utf-8 escapes (%uXXXX - codes) in URLs. - - Version 2.752 - - 1. Syntax error in the autoloaded Fh::new() subroutine. - 2. Better error reporting in autoloaded functions. - - Version 2.751 - - 1. Tiny tweak to filename regular expression function on line 3355. - - Version 2.75 - - 1. Fixed bug in server push boundary strings (CGI.pm and CGI::Push). - 2. Fixed bug that occurs when uploading files with funny characters - in the name - 3. Fixed non-XHTML-compliant attributes produced by textfield() - 4. Added EPOC support, courtesy Olaf Flebbe - 5. Fixed minor XHTML bugs. - 6. Made escape() and unescape() symmetric with respect to EBCDIC, - courtesy Roca, Ignasi <ignasi.roca@fujitsu.siemens.es> - 7. Removed uninitialized variable warning from CGI::Cookie, provided - by Atipat Rojnuckarin <rojnuca@yahoo.com> - 8. Fixed bug in CGI::Pretty that causes it to print partial end tags - when the $INDENT global is changed. - 9. Single quotes are changed to character entity ' for compatibility - with URLs. - - Version 2.74 - - September 13, 2000 - 1. Quashed one-character bug that caused CGI.pm to fail on file - uploads. - - Version 2.73 - - September 12, 2000 - 1. Added -base to the list of arguments accepted by url(). - 2. Fixes to XHTML support. - 3. POST parameters no longer show up in the Location box. - - Version 2.72 - - August 19, 2000 - 1. Fixed the defaults button so that it works again - 2. Charset is now correctly saved and restored when saving to files - 3. url() now works correctly when given scripts with %20 and other - escapes in the additional path info. This undoes a patch - introduced in version 2.47 that I no longer understand the - rationale for. - - Version 2.71 - - August 13, 2000 - 1. Newlines in the value attributes of hidden fields and other form - elements are now escaped when using ISO-Latin. - 2. Inline script and style sections are now protected as CDATA - sections when XHTML mode is on (the default). - - Version 2.70 - - August 4, 2000 - 1. Fixed bug in scrolling_list() which omitted a space in front of - the "multiple" attribute. - 2. Squashed the "useless use of string in void context" message from - redirects. - - Version 2.69 - - 1. startform() now creates default ACTION for POSTs as well as GETs. - This may break some browsers, but it no longer violates the HTML - spec. - 2. CGI.pm now emits XHTML by default. Disable with -no_xhtml. - 3. We no longer interpret &#ddd sequences in non-latin character - sets. - - Version 2.68 - - 1. No longer attempts to escape characters when dealing with non - ISO-8861 character sets. - 2. checkbox() function now defaults to using -value as its label, - rather than -name. The current behavior is what has been - documented from the beginning. - 3. -style accepts array reference to incorporate multiple stylesheets - into document. - - 1. Fixed two bugs that caused the -compile pragma to fail with a - syntax error. - - Version 2.67 - - 1. Added XHTML support (incomplete; tags need to be lowercased). - 2. Fixed CGI/Carp when running under mod_perl. Probably broke in - other contexts. - 3. Fixed problems when passing multiple cookies. - 4. Suppress warnings from _tableize() that were appearing when using - -w switch with radio_group() and checkbox_group(). - 5. Support for the header() -attachment argument, which can give - pages a default file name when saving to disk. - - Version 2.66 - - 1. 2.65 changes in make_attributes() broke HTTP header functions - (including redirect), so made it context sensitive. - - Version 2.65 - - 1. Fixed regression tests to skip tests that require implicit fork on - machines without fork(). - 2. Changed make_attributes() to automatically escape any HTML - reserved characters. - 3. Minor documentation fix in javascript example. - - Version 2.64 - - 1. Changes introduced in 2.63 broke param() when retrieving parameter - lists containing only a single argument. This is now fixed. - 2. self_url() now defaults to returning parameters delimited with - semicolon. Use the pragma -oldstyle_urls to get the old "&" - delimiter. - - Version 2.63 - - 1. Fixed CGI::Push to pull out parameters correctly. - 2. Fixed redirect() so that it works with default character set - 3. Changed param() so as to returned empty string '' when referring - to variables passed in query strings like 'name1=&name2' - - Version 2.62 - - 1. Fixed broken ReadParse() function, and added regression tests - 2. Fixed broken CGI::Pretty, and added regression tests - - Version 2.61 - - 1. Moved more functions from CGI.pm proper into CGI/Util.pm. - CGI/Cookie should now be standalone. - 2. Disabled per-user temporary directories, which were causing grief. - - Version 2.60 - - 1. Fixed junk appearing in autogenerated HTML functions when using - object-oriented mode. - - Version 2.59 - - 1. autoescape functionality breaks too much existing code, removed - it. - 2. use escapeHTML() manually - - Version 2.58 - - This is the release version of 2.57. - - Version 2.57 - - 1. Added -debug pragma and turned off auto reading of STDIN. - 2. Default DTD updated to HTML 4.01 transitional. - 3. Added charset() method and the -charset argument to header(). - 4. Fixed behavior of escapeHTML() to respect charset() and to escape - nasty Windows characters (thanks to Tom Christiansen). - 5. Handle REDIRECT_QUERY_STRING correctly. - 6. Removed use_named_parameters() because of dependency problems and - general lameness. - 7. Fixed problems with bad HREF links generated by url(-relative=>1) - when the url is like /people/. - 8. Silenced a warning on upload (patch provided by Jonas Liljegren) - 9. Fixed race condition in CGI::Carp when errors occur during parsing - (patch provided by Maurice Aubrey). - 10. Fixed failure of url(-path_info=>1) when path contains % signs. - 11. Fixed warning from CGI::Cookie when receiving foreign cookies that - don't use name=value format. - 12. Fixed incompatibilities with file uploading on VMS systems. - - Version 2.56 - - 1. Fixed bugs in file upload introduced in version 2.55 - 2. Fixed long-standing bug that prevented two files with identical - names from being uploaded. - - Version 2.55 - - 1. Fixed cookie regression test so as not to produce an error. - 2. Fixed path_info() and self_url() to work correctly together when - path_info() modified. - 3. Removed manify warnings from CGI::{Switch,Apache}. - - Version 2.54 - - 1. This will be the last release of the monolithic CGI.pm module. - Later versions will be modularized and optimized. - 2. DOMAIN tag no longer added to cookies by default. This will break - some versions of Internet Explorer, but will avoid breaking - networks which use host tables without fully qualified domain - names. For compatibility, please always add the -domain tag when - creating cookies. - 3. Fixed escape() method so that +'s are treated correctly. - 4. Updated CGI::Pretty module. - - Version 2.53 - - 1. Forgot to upgrade regression tests before releasing 2.52. NOTHING - ELSE HAS CHANGED IN LIBRARY - - Version 2.52 - - 1. Spurious newline in checkbox() routine removed. (courtesy John - Essen) - 2. TEXTAREA linebreaks now respected in dump() routine. (courtesy - John Essen) - 3. Patches for DOS ports (courtesy Robert Davies) - 4. Patches for VMS - 5. More fixes for cookie problems - 6. Fix CGI::Carp so that it doesn't affect eval{} blocks (courtesy - Byron Brummer) - - Version 2.51 - - 1. Fixed problems with cookies not being remembered when sent to IE - 5.0 (and Netscape 5.0 too?) - 2. Numerous HTML compliance problems in cgi_docs.html; fixed thanks - to Michael Leahy - - Version 2.50 - - 1. Added a new Vars() method to retrieve all parameters as a tied - hash. - 2. Untainted tainted tempfile name so that script doesn't fail on - terminal unlink. - 3. Made picking of upload tempfile name more intelligent so that - doesn't fail in case of name collision. - 4. Fixed handling of expire times when passed an absolute timestamp. - 5. Changed dump() to Dump() to avoid name clashes. - - Version 2.49 - - 1. Fixes for FastCGI (globals not getting reset) - 2. Fixed url() to correctly handle query string and path under - MOD_PERL - - Version 2.48 - - 1. Reverted detection of MOD_PERL to avoid breaking PerlEX. - - Version 2.47 - - 1. Patch to fix file upload bug appearing in IE 3.01 for - Macintosh/PowerPC. - 2. Replaced use of $ENV{SCRIPT_NAME} with $ENV{REQUEST_URI} when - running under Apache, to fix self-referencing URIs. - 3. Fixed bug in escapeHTML() which caused certain constructs, such as - CGI->image_button(), to fail. - 4. Fixed bug which caused strong('CGI') to fail. Be careful to use - CGI::strong('CGI') and not CGI->strong('CGI'). The latter will - produce confusing results. - 5. Added upload() function, as a preferred replacement for the - "filehandle as string" feature. - 6. Added cgi_error() function. - 7. Rewrote file upload handling to return undef rather than dieing - when an error is encountered. Be sure to call cgi_error() to find - out what went wrong. - - Version 2.46 - - 1. Fix for failure of the "include" tests under mod_perl - 2. Added end_multipart_form to prevent failures during qw(-compile - :all) - - Version 2.45 - - 1. Multiple small documentation fixes - 2. CGI::Pretty didn't get into 2.44. Fixed now. - - Version 2.44 - - 1. Fixed file descriptor leak in upload function. - 2. Fixed bug in header() that prevented fields from containing double - quotes. - 3. Added Brian Paulsen's CGI::Pretty package for pretty-printing - output HTML. - 4. Removed CGI::Apache and CGI::Switch from the distribution. - 5. Generated start_* shortcuts so that start_table(), end_table(), - start_ol(), end_ol(), and so forth now work (see the docs on how - to enable this feature). - 6. Changed accept() to Accept(), sub() to Sub(). There's still a - conflict with reset(), but this will break too many existing - scripts! - - Version 2.43 - - 1. Fixed problem with "use strict" and file uploads (thanks to Peter - Haworth) - 2. Fixed problem with not MSIE 3.01 for the power_mac not doing file - uploads right. - 3. Fixed problem with file upload on IIS 4.0 when authorization in - use. - 4. -content_type and '-content-type' can now be provided to header() - as synonyms for -type. - 5. CGI::Carp now escapes the ampersand BEFORE escaping the > and < - signs. - 6. Fixed "not an array reference" error when passing a hash reference - to radio_group(). - 7. Fixed non-removal of uploaded TMP files on NT platforms which - occurs when server runs on non-C drive (thanks to Steve Kilbane - for finding this one). - - Version 2.42 - - 1. Too many screams of anguish at changed behavior of url(). Is now - back to its old behavior by default, with options to generate all - the variants. - 2. Added regression tests. "make test" now works. - 3. Documentation fixes. - 4. Fixes for Macintosh uploads, but uploads STILL do not work pending - changes to MacPerl. - - Version 2.41 - - 1. url() method now includes the path info. Use script_name() to get - it without path info(). - 2. Changed handling of empty attributes in HTML tag generation. Be - warned! Use table({-border=>undef}) rather than - table({-border=>''}). - 3. Changes to allow uploaded filenames to be compared to other - strings with "eq", "cmp" and "ne". - 4. Changes to allow CGI.pm to coexist more peacefully with - ActiveState PerlEX. - 5. Changes to prevent exported variables from clashing when importing - ":all" set in combination with cookies. - - Version 2.40 - - 1. CGI::Carp patched to work better with mod_perl (thanks to Chris - Dean). - 2. Uploads of files whose names begin with numbers or the Windows - \\UNC\shared\file nomenclature should no longer fail. - 3. The <STYLE> tag (for cascading style sheets) now generates the - required TYPE attribute. - 4. Server push primitives added, thanks to Ed Jordan. - 5. Table and other HTML3 functions are now part of the :standard set. - 6. Small documentation fixes. - - TO DO: - 1. Do something about the DTD mess. The module should generate - correct DTDs, or at least offer the programmer a way to specify - the correct one. - 2. Split CGI.pm into CGI processing and HTML-generating modules. - 3. More robust file upload (?still not working on the Macintosh?). - 4. Bring in all the HTML4 functionality, particular the accessibility - features. - - Version 2.39 - - 1. file uploads failing because of VMS patch; fixed. - 2. -dtd parameter was not being properly processed. - - Version 2.38 - - I finally got tired of all the 2.37 betas and released 2.38. The main - difference between this version and the last 2.37 beta (2.37b30) are - some fixes for VMS. This should allow file upload to work properly on - all VMS Web servers. - - Version 2.37, various beta versions - - 1. Added a CGI::Cookie::parse() method for lucky mod_perl users. - 2. No longer need separate -values and -labels arguments for - multi-valued form elements. - 3. Added better interface to raw cookies (fix courtesy Ken Fox, - kfox@ford.com) - 4. Added param_fetch() function for direct access to parameter list. - 5. Fix to checkbox() to allow for multi-valued single checkboxes - (weird problem). - 6. Added a compile() method for those who want to compile without - importing. - 7. Documented the import pragmas a little better. - 8. Added a -compile switch to the use clause for the long-suffering - mod_perl and Perl compiler users. - 9. Fixed initialization routines so that FileHandle and type globs - work correctly (and hash initialization doesn't fail!). - 10. Better deletion of temporary files on NT systems. - 11. Added documentation on escape(), unescape(), unescapeHTML() and - unescapeHTML() subroutines. - 12. Added documentation on creating subclasses. - 13. Fixed problem when calling $self->SUPER::foo() from inheriting - subclasses. - 14. Fixed problem using filehandles from within subroutines. - 15. Fixed inability to use the string "CGI" as a parameter. - 16. Fixed exponentially growing $FILLUNIT bug - 17. Check for undef filehandle in read_from_client() - 18. Now requires the UNIVERSAL.pm module, present in Perl 5.003_7 or - higher. - 19. Fixed problem with uppercase-only parameters being ignored. - 20. Fixed vanishing cookie problem. - 21. Fixed warning in initialize_globals() under mod_perl. - 22. File uploads from Macintosh versions of MSIE should now work. - 23. Pragmas now preceded by dashes (-nph) rather than colons (:nph). - Old style is supported for backward compatability. - 24. Can now pass arguments to all functions using {} brackets, - resolving historical inconsistencies. - 25. Removed autoloader warnings about absent MultipartBuffer::DESTROY. - 26. Fixed non-sticky checkbox() when -name used without -value. - 27. Hack to fix path_info() in IIS 2.0. Doesn't help with IIS 3.0. - 28. Parameter syntax for debugging from command line now more - straightforward. - 29. Added $DISABLE_UPLOAD to disable file uploads. - 30. Added $POST_MAX to error out if POSTings exceed some ceiling. - 31. Fixed url_param(), which wasn't working at all. - 32. Fixed variable suicide problem in s///e expressions, where the - autoloader was needed during evaluation. - 33. Removed excess spaces between elements of checkbox and radio - groups - 34. Can now create "valueless" submit buttons - 35. Can now set path_info as well as read it. - 36. ReadParse() now returns a useful function result. - 37. import_names() now allows you to optionally clear out the - namespace before importing (for mod_perl users) - 38. Made it possible to have a popup menu or radio button with a value - of "0". - 39. link() changed to Link() to avoid overriding native link function. - 40. Takes advantage of mod_perl's register_cleanup() function to clear - globals. - 41. <LAYER> and <ILAYER> added to :html3 functions. - 42. Fixed problems with private tempfiles and NT/IIS systems. - 43. No longer prints the DTD by default (I bet no one will complain). - 44. Allow underscores to replace internal hyphens in parameter names. - 45. CGI::Push supports heterogeneous MIME types and adjustable delays - between pages. - 46. url_param() method added for retrieving URL parameters even when a - fill-out form is POSTed. - 47. Got rid of warnings when radio_group() is called. - 48. Cookies now moved to their very own module. - 49. Fixed documentation bug in CGI::Fast. - 50. Added a :no_debug pragma to the import list. - - Version 2.36 - - 1. Expanded JavaScript functionality - 2. Preliminary support for cascading stylesheets - 3. Security fixes for file uploads: - + Module will bail out if its temporary file already exists - + Temporary files can now be made completely private to avoid - peeking by other users or CGI scripts. - 4. use CGI qw/:nph/ wasn't working correctly. Now it is. - 5. Cookie and HTTP date formats didn't meet spec. Thanks to Mark - Fisher (fisherm@indy.tce.com) for catching and fixing this. - - p - - Version 2.35 - - 1. Robustified multipart file upload against incorrect syntax in - POST. - 2. Fixed more problems with mod_perl. - 3. Added -noScript parameter to start_html(). - 4. Documentation fixes. - - Version 2.34 - - 1. Stupid typo fix - - Version 2.33 - - 1. Fixed a warning about an undefined environment variable. - 2. Doug's patch for redirect() under mod_perl - 3. Partial fix for busted inheritence from CGI::Apache - 4. Documentation fixes. - - Version 2.32 - - 1. Improved support for Apache's mod_perl. - 2. Changes to better support inheritance. - 3. Support for OS/2. - - Version 2.31 - - 1. New uploadInfo() method to obtain header information from uploaded - files. - 2. cookie() without any arguments returns all the cookies passed to a - script. - 3. Removed annoying warnings about $ENV{NPH} when running with the -w - switch. - 4. Removed operator overloading throughout to make compatible with - new versions of perl. - 5. -expires now implies the -date header, to avoid clock skew. - 6. WebSite passes cookies in $ENV{COOKIE} rather than - $ENV{HTTP_COOKIE}. We now handle this, even though it's O'Reilly's - fault. - 7. Tested successfully against new sfio I/O layer. - 8. Documentation fixes. - - Version 2.30 - - 1. Automatic detection of operating system at load time. - 2. Changed select() function to Select() in order to avoid conflict - with Perl built-in. - 3. Added Tr() as an alternative to TR(); some people think it looks - better that way. - 4. Fixed problem with autoloading of MultipartBuffer::DESTROY code. - 5. Added the following methods: - + virtual_host() - + server_software() - 6. Automatic NPH mode when running under Microsoft IIS server. - - Version 2.29 - - 1. Fixed cookie bugs - 2. Fixed problems that cropped up when useNamedParameters was set to - 1. - 3. Prevent CGI::Carp::fatalsToBrowser() from crapping out when - encountering a die() within an eval(). - 4. Fixed problems with filehandle initializers. - - Version 2.28 - - 1. Added support for NPH scripts; also fixes problems with Microsoft - IIS. - 2. Fixed a problem with checkbox() values not being correctly saved - and restored. - 3. Fixed a bug in which CGI objects created with empty string - initializers took on default values from earlier CGI objects. - 4. Documentation fixes. - - Version 2.27 - - 1. Small but important bug fix: the automatic capitalization of tag - attributes was accidentally capitalizing the VALUES as well as the - ATTRIBUTE names (oops). - - Version 2.26 - - 1. Changed behavior of scrolling_list(), checkbox() and - checkbox_group() methods so that defaults are honored correctly. - The "fix" causes endform() to generate additional <INPUT - TYPE="HIDDEN"> tags -- don't be surpised. - 2. Fixed bug involving the detection of the SSL protocol. - 3. Fixed documentation error in position of the -meta argument in - start_html(). - 4. HTML shortcuts now generate tags in ALL UPPERCASE. - 5. start_html() now generates correct SGML header: - <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> - - 6. CGI::Carp no longer fails "use strict refs" pragma. - - Version 2.25 - - 1. Fixed bug that caused bad redirection on destination URLs with - arguments. - 2. Fixed bug involving use_named_parameters() followed by - start_multipart_form() - 3. Fixed bug that caused incorrect determination of binmode for - Macintosh. - 4. Spelling fixes on documentation. - - Version 2.24 - - 1. Fixed bug that caused generation of lousy HTML for some form - elements - 2. Fixed uploading bug in Windows NT - 3. Some code cleanup (not enough) - - Version 2.23 - - 1. Fixed an obscure bug that caused scripts to fail mysteriously. - 2. Fixed auto-caching bug. - 3. Fixed bug that prevented HTML shortcuts from passing taint checks. - 4. Fixed some -w warning problems. - - Version 2.22 - - 1. New CGI::Fast module for use with FastCGI protocol. See pod - documentation for details. - 2. Fixed problems with inheritance and autoloading. - 3. Added TR() (<tr>) and PARAM() (<param>) methods to list of - exported HTML tag-generating functions. - 4. Moved all CGI-related I/O to a bottleneck method so that this can - be overridden more easily in mod_perl (thanks to Doug MacEachern). - 5. put() method as substitute for print() for use in mod_perl. - 6. Fixed crash in tmpFileName() method. - 7. Added tmpFileName(), startform() and endform() to export list. - 8. Fixed problems with attributes in HTML shortcuts. - 9. Functions that don't actually need access to the CGI object now no - longer generate a default one. May speed things up slightly. - 10. Aesthetic improvements in generated HTML. - 11. New examples. - - Version 2.21 - - 1. Added the -meta argument to start_html(). - 2. Fixed hidden fields (again). - 3. Radio_group() and checkbox_group() now return an appropriate - scalar value when called in a scalar context, rather than - returning a numeric value! - 4. Cleaned up the formatting of form elements to avoid unesthetic - extra spaces within the attributes. - 5. HTML elements now correctly include the closing tag when - parameters are present but null: em('') - 6. Added password_field() to the export list. - - Version 2.20 - - 1. Dumped the SelfLoader because of problems with running with taint - checks and rolled my own. Performance is now significantly - improved. - 2. Added HTML shortcuts. - 3. import() now adheres to the Perl module conventions, allowing - CGI.pm to import any or all method names into the user's name - space. - 4. Added the ability to initialize CGI objects from strings and - associative arrays. - 5. Made it possible to initialize CGI objects with filehandle - references rather than filehandle strings. - 6. Added the delete_all() and append() methods. - 7. CGI objects correctly initialize from filehandles on NT/95 systems - now. - 8. Fixed the problem with binary file uploads on NT/95 systems. - 9. Fixed bug in redirect(). - 10. Added '-Window-target' parameter to redirect(). - 11. Fixed import_names() so that parameter names containing funny - characters work. - 12. Broke the unfortunate connection between cookie and CGI parameter - name space. - 13. Fixed problems with hidden fields whose values are 0. - 14. Cleaned up the documentation somewhat. - - Version 2.19 - - 1. Added cookie() support routines. - 2. Added -expires parameter to header(). - 3. Added cgi-lib.pl compatability mode. - 4. Made the module more configurable for different operating systems. - 5. Fixed a dumb bug in JavaScript button() method. - - Version 2.18 - - 1. Fixed a bug that corrects a hang that occurs on some platforms - when processing file uploads. Unfortunately this disables the - check for bad Netscape uploads. - 2. Fixed bizarre problem involving the inability to process uploaded - files that begin with a non alphabetic character in the file name. - 3. Fixed a bug in the hidden fields involving the -override directive - being ignored when scalar defaults were passed. - 4. Added documentation on how to disable the SelfLoader features. - - Version 2.17 - - 1. Added support for the SelfLoader module. - 2. Added oodles of JavaScript support routines. - 3. Fixed bad bug in query_string() method that caused some parameters - to be silently dropped. - 4. Robustified file upload code to handle premature termination by - the client. - 5. Exported temporary file names on file upload. - 6. Removed spurious "uninitialized variable" warnings that appeared - when running under 5.002. - 7. Added the Carp.pm library to the standard distribution. - 8. Fixed a number of errors in this documentation, and probably added - a few more. - 9. Checkbox_group() and radio_group() now return the buttons as - arrays, so that you can incorporate the individual buttons into - specialized tables. - 10. Added the '-nolabels' option to checkbox_group() and - radio_group(). Probably should be added to all the other - HTML-generating routines. - 11. Added the url() method to recover the URL without the entire query - string appended. - 12. Added request_method() to list of environment variables available. - 13. Would you believe it? Fixed hidden fields again! - - Version 2.16 - - 1. Fixed hidden fields yet again. - 2. Fixed subtle problems in the file upload method that caused - intermittent failures (thanks to Keven Hendrick for this one). - 3. Made file upload more robust in the face of bizarre behavior by - the Macintosh and Windows Netscape clients. - 4. Moved the POD documentation to the bottom of the module at the - request of Stephen Dahmen. - 5. Added the -xbase parameter to the start_html() method, also at the - request of Stephen Dahmen. - 6. Added JavaScript form buttons at Stephen's request. I'm not sure - how to use this Netscape extension correctly, however, so for now - the form() method is in the module as an undocumented feature. Use - at your own risk! - - Version 2.15 - - 1. Added the -override parameter to all field-generating methods. - 2. Documented the user_name() and remote_user() methods. - 3. Fixed bugs that prevented empty strings from being recognized as - valid textfield contents. - 4. Documented the use of framesets and added a frameset example. - - Version 2.14 - - This was an internal experimental version that was never released. - - Version 2.13 - - 1. Fixed a bug that interfered with the value "0" being entered into - text fields. - - Version 2.01 - - 1. Added -rows and -columns to the radio and checkbox groups. No - doubt this will cause much grief because it seems to promise a - level of meta-organization that it doesn't actually provide. - 2. Fixed a bug in the redirect() method -- it was not truly HTTP/1.0 - compliant. - - Version 2.0 - - The changes seemed to touch every line of code, so I decided to bump - up the major version number. - 1. Support for named parameter style method calls. This turns out - to be a big win for extending CGI.pm when Netscape adds new HTML - "features". - 2. Changed behavior of hidden fields back to the correct "sticky" - behavior. This is going to break some programs, but it is for - the best in the long run. - 3. Netscape 2.0b2 broke the file upload feature. CGI.pm now handles - both 2.0b1 and 2.0b2-style uploading. It will probably break again - in 2.0b3. - 4. There were still problems with library being unable to distinguish - between a form being loaded for the first time, and a subsequent - loading with all fields blank. We now forcibly create a default - name for the Submit button (if not provided) so that there's - always at least one parameter. - 5. More workarounds to prevent annoying spurious warning messages - when run under the -w switch. -w is seriously broken in perl - 5.001! - - Version 1.57 - - 1. Support for the Netscape 2.0 "File upload" field. - 2. The handling of defaults for selected items in scrolling lists and - multiple checkboxes is now consistent. - - Version 1.56 - - 1. Created true "pod" documentation for the module. - 2. Cleaned up the code to avoid many of the spurious "use of - uninitialized variable" warnings when running with the -w switch. - 3. Added the autoEscape() method. v - 4. Added string interpolation of the CGI object. - 5. Added the ability to pass additional parameters to the <BODY> tag. - 6. Added the ability to specify the status code in the HTTP header. - - Bug fixes in version 1.55 - - 1. Every time self_url() was called, the parameter list would grow. - This was a bad "feature". - 2. Documented the fact that you can pass "-" to radio_group() in - order to prevent any button from being highlighted by default. - - Bug fixes in version 1.54 - - 1. The user_agent() method is now documented; - 2. A potential security hole in import() is now plugged. - 3. Changed name of import() to import_names() for compatability with - CGI:: modules. - - Bug fixes in version 1.53 - - 1. Fixed several typos in the code that were causing the following - subroutines to fail in some circumstances - 1. checkbox() - 2. hidden() - 2. No features added - - New features added in version 1.52 - - 1. Added backslashing, quotation marks, and other shell-style escape - sequences to the parameters passed in during debugging off-line. - 2. Changed the way that the hidden() method works so that the default - value always overrides the current one. - 3. Improved the handling of sticky values in forms. It's now less - likely that sticky values will get stuck. - 4. If you call server_name(), script_name() and several other methods - when running offline, the methods now create "dummy" values to - work with. - - Bugs fixed in version 1.51 - - 1. param() when called without arguments was returning an array of - length 1 even when there were no parameters to be had. Bad bug! - Bad! - 2. The HTML code generated would break if input fields contained the - forbidden characters ">< or &. You can now use these characters - freely. - - New features added in version 1.50 - - 1. import() method allows all the parameters to be imported into a - namespace in one fell swoop. - 2. Parameters are now returned in the same order in which they were - defined. - - Bugs fixed in version 1.45 - - 1. delete() method didn't work correctly. This is now fixed. - 2. reset() method didn't allow you to set the name of the button. - Fixed. - - Bugs fixed in version 1.44 - - 1. self_url() didn't include the path information. This is now fixed. - - New features added in version 1.43 - - 1. Added the delete() method. - - New features added in version 1.42 - - 1. The image_button() method to create clickable images. - 2. A few bug fixes involving forms embedded in <PRE> blocks. - - New features added in version 1.4 - - 1. New header shortcut methods - + redirect() to create HTTP redirection messages. - + start_html() to create the HTML title, complete with the - recommended <LINK> tag that no one ever remembers to include. - + end_html() for completeness' sake. - 2. A new save() method that allows you to write out the state of an - script to a file or pipe. - 3. An improved version of the new() method that allows you to restore - the state of a script from a file or pipe. With (2) this gives you - dump and restore capabilities! (Wow, you can put a "121,931 - customers served" banner at the bottom of your pages!) - 4. A self_url() method that allows you to create state-maintaining - hypertext links. In addition to allowing you to maintain the state - of your scripts between invocations, this lets you work around a - problem that some browsers have when jumping to internal links in - a document that contains a form -- the form information gets lost. - 5. The user-visible labels in checkboxes, radio buttons, popup menus - and scrolling lists have now been decoupled from the values sent - to your CGI script. Your script can know a checkbox by the name of - "cb1" while the user knows it by a more descriptive name. I've - also added some parameters that were missing from the text fields, - such as MAXLENGTH. - 6. A whole bunch of methods have been added to get at environment - variables involved in user verification and other obscure - features. - - Bug fixes - - 1. The problems with the hidden fields have (I hope at last) been - fixed. - 2. You can create multiple query objects and they will all be - initialized correctly. This simplifies the creation of multiple - forms on one page. - 3. The URL unescaping code works correctly now. diff --git a/ext/CGI/lib/CGI/Cookie.pm b/ext/CGI/lib/CGI/Cookie.pm deleted file mode 100644 index f2535f466d..0000000000 --- a/ext/CGI/lib/CGI/Cookie.pm +++ /dev/null @@ -1,546 +0,0 @@ -package CGI::Cookie; - -# See the bottom of this file for the POD documentation. Search for the -# string '=head'. - -# You can run this file through either pod2man or pod2html to produce pretty -# documentation in manual or html file format (these utilities are part of the -# Perl 5 distribution). - -# Copyright 1995-1999, Lincoln D. Stein. All rights reserved. -# It may be used and modified freely, but I do request that this copyright -# notice remain attached to the file. You may modify this module as you -# wish, but if you redistribute a modified version, please attach a note -# listing the modifications you have made. - -$CGI::Cookie::VERSION='1.29'; - -use CGI::Util qw(rearrange unescape escape); -use CGI; -use overload '""' => \&as_string, - 'cmp' => \&compare, - 'fallback'=>1; - -my $PERLEX = 0; -# Turn on special checking for ActiveState's PerlEx -$PERLEX++ if defined($ENV{'GATEWAY_INTERFACE'}) && $ENV{'GATEWAY_INTERFACE'} =~ /^CGI-PerlEx/; - -# Turn on special checking for Doug MacEachern's modperl -# PerlEx::DBI tries to fool DBI by setting MOD_PERL -my $MOD_PERL = 0; -if (exists $ENV{MOD_PERL} && ! $PERLEX) { - if (exists $ENV{MOD_PERL_API_VERSION} && $ENV{MOD_PERL_API_VERSION} == 2) { - $MOD_PERL = 2; - require Apache2::RequestUtil; - require APR::Table; - } else { - $MOD_PERL = 1; - require Apache; - } -} - -# fetch a list of cookies from the environment and -# return as a hash. the cookies are parsed as normal -# escaped URL data. -sub fetch { - my $class = shift; - my $raw_cookie = get_raw_cookie(@_) or return; - return $class->parse($raw_cookie); -} - -# Fetch a list of cookies from the environment or the incoming headers and -# return as a hash. The cookie values are not unescaped or altered in any way. - sub raw_fetch { - my $class = shift; - my $raw_cookie = get_raw_cookie(@_) or return; - my %results; - my($key,$value); - - my @pairs = split("[;,] ?",$raw_cookie); - foreach (@pairs) { - s/\s*(.*?)\s*/$1/; - if (/^([^=]+)=(.*)/) { - $key = $1; - $value = $2; - } - else { - $key = $_; - $value = ''; - } - $results{$key} = $value; - } - return \%results unless wantarray; - return %results; -} - -sub get_raw_cookie { - my $r = shift; - $r ||= eval { $MOD_PERL == 2 ? - Apache2::RequestUtil->request() : - Apache->request } if $MOD_PERL; - if ($r) { - $raw_cookie = $r->headers_in->{'Cookie'}; - } else { - if ($MOD_PERL && !exists $ENV{REQUEST_METHOD}) { - die "Run $r->subprocess_env; before calling fetch()"; - } - $raw_cookie = $ENV{HTTP_COOKIE} || $ENV{COOKIE}; - } -} - - -sub parse { - my ($self,$raw_cookie) = @_; - my %results; - - my @pairs = split("[;,] ?",$raw_cookie); - foreach (@pairs) { - s/\s*(.*?)\s*/$1/; - my($key,$value) = split("=",$_,2); - - # Some foreign cookies are not in name=value format, so ignore - # them. - next if !defined($value); - my @values = (); - if ($value ne '') { - @values = map unescape($_),split(/[&;]/,$value.'&dmy'); - pop @values; - } - $key = unescape($key); - # A bug in Netscape can cause several cookies with same name to - # appear. The FIRST one in HTTP_COOKIE is the most recent version. - $results{$key} ||= $self->new(-name=>$key,-value=>\@values); - } - return \%results unless wantarray; - return %results; -} - -sub new { - my $class = shift; - $class = ref($class) if ref($class); - # Ignore mod_perl request object--compatability with Apache::Cookie. - shift if ref $_[0] - && eval { $_[0]->isa('Apache::Request::Req') || $_[0]->isa('Apache') }; - my($name,$value,$path,$domain,$secure,$expires,$httponly) = - rearrange([NAME,[VALUE,VALUES],PATH,DOMAIN,SECURE,EXPIRES,HTTPONLY],@_); - - # Pull out our parameters. - my @values; - if (ref($value)) { - if (ref($value) eq 'ARRAY') { - @values = @$value; - } elsif (ref($value) eq 'HASH') { - @values = %$value; - } - } else { - @values = ($value); - } - - bless my $self = { - 'name'=>$name, - 'value'=>[@values], - },$class; - - # IE requires the path and domain to be present for some reason. - $path ||= "/"; - # however, this breaks networks which use host tables without fully qualified - # names, so we comment it out. - # $domain = CGI::virtual_host() unless defined $domain; - - $self->path($path) if defined $path; - $self->domain($domain) if defined $domain; - $self->secure($secure) if defined $secure; - $self->expires($expires) if defined $expires; - $self->httponly($httponly) if defined $httponly; -# $self->max_age($expires) if defined $expires; - return $self; -} - -sub as_string { - my $self = shift; - return "" unless $self->name; - - my(@constant_values,$domain,$path,$expires,$max_age,$secure,$httponly); - - push(@constant_values,"domain=$domain") if $domain = $self->domain; - push(@constant_values,"path=$path") if $path = $self->path; - push(@constant_values,"expires=$expires") if $expires = $self->expires; - push(@constant_values,"max-age=$max_age") if $max_age = $self->max_age; - push(@constant_values,"secure") if $secure = $self->secure; - push(@constant_values,"HttpOnly") if $httponly = $self->httponly; - - my($key) = escape($self->name); - my($cookie) = join("=",(defined $key ? $key : ''),join("&",map escape(defined $_ ? $_ : ''),$self->value)); - return join("; ",$cookie,@constant_values); -} - -sub compare { - my $self = shift; - my $value = shift; - return "$self" cmp $value; -} - -sub bake { - my ($self, $r) = @_; - - $r ||= eval { - $MOD_PERL == 2 - ? Apache2::RequestUtil->request() - : Apache->request - } if $MOD_PERL; - if ($r) { - $r->headers_out->add('Set-Cookie' => $self->as_string); - } else { - print CGI::header(-cookie => $self); - } - -} - -# accessors -sub name { - my $self = shift; - my $name = shift; - $self->{'name'} = $name if defined $name; - return $self->{'name'}; -} - -sub value { - my $self = shift; - my $value = shift; - if (defined $value) { - my @values; - if (ref($value)) { - if (ref($value) eq 'ARRAY') { - @values = @$value; - } elsif (ref($value) eq 'HASH') { - @values = %$value; - } - } else { - @values = ($value); - } - $self->{'value'} = [@values]; - } - return wantarray ? @{$self->{'value'}} : $self->{'value'}->[0] -} - -sub domain { - my $self = shift; - my $domain = shift; - $self->{'domain'} = lc $domain if defined $domain; - return $self->{'domain'}; -} - -sub secure { - my $self = shift; - my $secure = shift; - $self->{'secure'} = $secure if defined $secure; - return $self->{'secure'}; -} - -sub expires { - my $self = shift; - my $expires = shift; - $self->{'expires'} = CGI::Util::expires($expires,'cookie') if defined $expires; - return $self->{'expires'}; -} - -sub max_age { - my $self = shift; - my $expires = shift; - $self->{'max-age'} = CGI::Util::expire_calc($expires)-time() if defined $expires; - return $self->{'max-age'}; -} - -sub path { - my $self = shift; - my $path = shift; - $self->{'path'} = $path if defined $path; - return $self->{'path'}; -} - - -sub httponly { # HttpOnly - my $self = shift; - my $httponly = shift; - $self->{'httponly'} = $httponly if defined $httponly; - return $self->{'httponly'}; -} - -1; - -=head1 NAME - -CGI::Cookie - Interface to Netscape Cookies - -=head1 SYNOPSIS - - use CGI qw/:standard/; - use CGI::Cookie; - - # Create new cookies and send them - $cookie1 = new CGI::Cookie(-name=>'ID',-value=>123456); - $cookie2 = new CGI::Cookie(-name=>'preferences', - -value=>{ font => Helvetica, - size => 12 } - ); - print header(-cookie=>[$cookie1,$cookie2]); - - # fetch existing cookies - %cookies = fetch CGI::Cookie; - $id = $cookies{'ID'}->value; - - # create cookies returned from an external source - %cookies = parse CGI::Cookie($ENV{COOKIE}); - -=head1 DESCRIPTION - -CGI::Cookie is an interface to Netscape (HTTP/1.1) cookies, an -innovation that allows Web servers to store persistent information on -the browser's side of the connection. Although CGI::Cookie is -intended to be used in conjunction with CGI.pm (and is in fact used by -it internally), you can use this module independently. - -For full information on cookies see - - http://www.ics.uci.edu/pub/ietf/http/rfc2109.txt - -=head1 USING CGI::Cookie - -CGI::Cookie is object oriented. Each cookie object has a name and a -value. The name is any scalar value. The value is any scalar or -array value (associative arrays are also allowed). Cookies also have -several optional attributes, including: - -=over 4 - -=item B<1. expiration date> - -The expiration date tells the browser how long to hang on to the -cookie. If the cookie specifies an expiration date in the future, the -browser will store the cookie information in a disk file and return it -to the server every time the user reconnects (until the expiration -date is reached). If the cookie species an expiration date in the -past, the browser will remove the cookie from the disk file. If the -expiration date is not specified, the cookie will persist only until -the user quits the browser. - -=item B<2. domain> - -This is a partial or complete domain name for which the cookie is -valid. The browser will return the cookie to any host that matches -the partial domain name. For example, if you specify a domain name -of ".capricorn.com", then Netscape will return the cookie to -Web servers running on any of the machines "www.capricorn.com", -"ftp.capricorn.com", "feckless.capricorn.com", etc. Domain names -must contain at least two periods to prevent attempts to match -on top level domains like ".edu". If no domain is specified, then -the browser will only return the cookie to servers on the host the -cookie originated from. - -=item B<3. path> - -If you provide a cookie path attribute, the browser will check it -against your script's URL before returning the cookie. For example, -if you specify the path "/cgi-bin", then the cookie will be returned -to each of the scripts "/cgi-bin/tally.pl", "/cgi-bin/order.pl", and -"/cgi-bin/customer_service/complain.pl", but not to the script -"/cgi-private/site_admin.pl". By default, the path is set to "/", so -that all scripts at your site will receive the cookie. - -=item B<4. secure flag> - -If the "secure" attribute is set, the cookie will only be sent to your -script if the CGI request is occurring on a secure channel, such as SSL. - -=item B<4. httponly flag> - -If the "httponly" attribute is set, the cookie will only be accessible -through HTTP Requests. This cookie will be inaccessible via JavaScript -(to prevent XSS attacks). - -But, currently this feature only used and recognised by -MS Internet Explorer 6 Service Pack 1 and later. - -See this URL for more information: - -L<http://msdn.microsoft.com/workshop/author/dhtml/httponly_cookies.asp> - -=back - -=head2 Creating New Cookies - - my $c = new CGI::Cookie(-name => 'foo', - -value => 'bar', - -expires => '+3M', - -domain => '.capricorn.com', - -path => '/cgi-bin/database', - -secure => 1 - ); - -Create cookies from scratch with the B<new> method. The B<-name> and -B<-value> parameters are required. The name must be a scalar value. -The value can be a scalar, an array reference, or a hash reference. -(At some point in the future cookies will support one of the Perl -object serialization protocols for full generality). - -B<-expires> accepts any of the relative or absolute date formats -recognized by CGI.pm, for example "+3M" for three months in the -future. See CGI.pm's documentation for details. - -B<-domain> points to a domain name or to a fully qualified host name. -If not specified, the cookie will be returned only to the Web server -that created it. - -B<-path> points to a partial URL on the current server. The cookie -will be returned to all URLs beginning with the specified path. If -not specified, it defaults to '/', which returns the cookie to all -pages at your site. - -B<-secure> if set to a true value instructs the browser to return the -cookie only when a cryptographic protocol is in use. - -B<-httponly> if set to a true value, the cookie will not be accessible -via JavaScript. - -For compatibility with Apache::Cookie, you may optionally pass in -a mod_perl request object as the first argument to C<new()>. It will -simply be ignored: - - my $c = new CGI::Cookie($r, - -name => 'foo', - -value => ['bar','baz']); - -=head2 Sending the Cookie to the Browser - -The simplest way to send a cookie to the browser is by calling the bake() -method: - - $c->bake; - -Under mod_perl, pass in an Apache request object: - - $c->bake($r); - -If you want to set the cookie yourself, Within a CGI script you can send -a cookie to the browser by creating one or more Set-Cookie: fields in the -HTTP header. Here is a typical sequence: - - my $c = new CGI::Cookie(-name => 'foo', - -value => ['bar','baz'], - -expires => '+3M'); - - print "Set-Cookie: $c\n"; - print "Content-Type: text/html\n\n"; - -To send more than one cookie, create several Set-Cookie: fields. - -If you are using CGI.pm, you send cookies by providing a -cookie -argument to the header() method: - - print header(-cookie=>$c); - -Mod_perl users can set cookies using the request object's header_out() -method: - - $r->headers_out->set('Set-Cookie' => $c); - -Internally, Cookie overloads the "" operator to call its as_string() -method when incorporated into the HTTP header. as_string() turns the -Cookie's internal representation into an RFC-compliant text -representation. You may call as_string() yourself if you prefer: - - print "Set-Cookie: ",$c->as_string,"\n"; - -=head2 Recovering Previous Cookies - - %cookies = fetch CGI::Cookie; - -B<fetch> returns an associative array consisting of all cookies -returned by the browser. The keys of the array are the cookie names. You -can iterate through the cookies this way: - - %cookies = fetch CGI::Cookie; - foreach (keys %cookies) { - do_something($cookies{$_}); - } - -In a scalar context, fetch() returns a hash reference, which may be more -efficient if you are manipulating multiple cookies. - -CGI.pm uses the URL escaping methods to save and restore reserved characters -in its cookies. If you are trying to retrieve a cookie set by a foreign server, -this escaping method may trip you up. Use raw_fetch() instead, which has the -same semantics as fetch(), but performs no unescaping. - -You may also retrieve cookies that were stored in some external -form using the parse() class method: - - $COOKIES = `cat /usr/tmp/Cookie_stash`; - %cookies = parse CGI::Cookie($COOKIES); - -If you are in a mod_perl environment, you can save some overhead by -passing the request object to fetch() like this: - - CGI::Cookie->fetch($r); - -=head2 Manipulating Cookies - -Cookie objects have a series of accessor methods to get and set cookie -attributes. Each accessor has a similar syntax. Called without -arguments, the accessor returns the current value of the attribute. -Called with an argument, the accessor changes the attribute and -returns its new value. - -=over 4 - -=item B<name()> - -Get or set the cookie's name. Example: - - $name = $c->name; - $new_name = $c->name('fred'); - -=item B<value()> - -Get or set the cookie's value. Example: - - $value = $c->value; - @new_value = $c->value(['a','b','c','d']); - -B<value()> is context sensitive. In a list context it will return -the current value of the cookie as an array. In a scalar context it -will return the B<first> value of a multivalued cookie. - -=item B<domain()> - -Get or set the cookie's domain. - -=item B<path()> - -Get or set the cookie's path. - -=item B<expires()> - -Get or set the cookie's expiration time. - -=back - - -=head1 AUTHOR INFORMATION - -Copyright 1997-1998, Lincoln D. Stein. All rights reserved. - -This library is free software; you can redistribute it and/or modify -it under the same terms as Perl itself. - -Address bug reports and comments to: lstein@cshl.org - -=head1 BUGS - -This section intentionally left blank. - -=head1 SEE ALSO - -L<CGI::Carp>, L<CGI> - -=cut diff --git a/ext/CGI/lib/CGI/Fast.pm b/ext/CGI/lib/CGI/Fast.pm deleted file mode 100644 index 594cad7501..0000000000 --- a/ext/CGI/lib/CGI/Fast.pm +++ /dev/null @@ -1,213 +0,0 @@ -package CGI::Fast; - -# See the bottom of this file for the POD documentation. Search for the -# string '=head'. - -# You can run this file through either pod2man or pod2html to produce pretty -# documentation in manual or html file format (these utilities are part of the -# Perl 5 distribution). - -# Copyright 1995,1996, Lincoln D. Stein. All rights reserved. -# It may be used and modified freely, but I do request that this copyright -# notice remain attached to the file. You may modify this module as you -# wish, but if you redistribute a modified version, please attach a note -# listing the modifications you have made. - -$CGI::Fast::VERSION='1.07'; - -use CGI; -use FCGI; -@ISA = ('CGI'); - -# workaround for known bug in libfcgi -while (($ignore) = each %ENV) { } - -# override the initialization behavior so that -# state is NOT maintained between invocations -sub save_request { - # no-op -} - -# If ENV{FCGI_SOCKET_PATH} is specified, we maintain a FCGI Request handle -# in this package variable. -use vars qw($Ext_Request); -BEGIN { - # If ENV{FCGI_SOCKET_PATH} is given, explicitly open the socket, - # and keep the request handle around from which to call Accept(). - if ($ENV{FCGI_SOCKET_PATH}) { - my $path = $ENV{FCGI_SOCKET_PATH}; - my $backlog = $ENV{FCGI_LISTEN_QUEUE} || 100; - my $socket = FCGI::OpenSocket( $path, $backlog ); - $Ext_Request = FCGI::Request( \*STDIN, \*STDOUT, \*STDERR, - \%ENV, $socket, 1 ); - } -} - -# New is slightly different in that it calls FCGI's -# accept() method. -sub new { - my ($self, $initializer, @param) = @_; - unless (defined $initializer) { - if ($Ext_Request) { - return undef unless $Ext_Request->Accept() >= 0; - } else { - return undef unless FCGI::accept() >= 0; - } - } - CGI->_reset_globals; - $self->_setup_symbols(@SAVED_SYMBOLS) if @CGI::SAVED_SYMBOLS; - return $CGI::Q = $self->SUPER::new($initializer, @param); -} - -1; - -=head1 NAME - -CGI::Fast - CGI Interface for Fast CGI - -=head1 SYNOPSIS - - use CGI::Fast qw(:standard); - $COUNTER = 0; - while (new CGI::Fast) { - print header; - print start_html("Fast CGI Rocks"); - print - h1("Fast CGI Rocks"), - "Invocation number ",b($COUNTER++), - " PID ",b($$),".", - hr; - print end_html; - } - -=head1 DESCRIPTION - -CGI::Fast is a subclass of the CGI object created by CGI.pm. It is -specialized to work well FCGI module, which greatly speeds up CGI -scripts by turning them into persistently running server processes. -Scripts that perform time-consuming initialization processes, such as -loading large modules or opening persistent database connections, will -see large performance improvements. - -=head1 OTHER PIECES OF THE PUZZLE - -In order to use CGI::Fast you'll need the FCGI module. See -http://www.cpan.org/ for details. - -=head1 WRITING FASTCGI PERL SCRIPTS - -FastCGI scripts are persistent: one or more copies of the script -are started up when the server initializes, and stay around until -the server exits or they die a natural death. After performing -whatever one-time initialization it needs, the script enters a -loop waiting for incoming connections, processing the request, and -waiting some more. - -A typical FastCGI script will look like this: - - #!/usr/bin/perl - use CGI::Fast; - &do_some_initialization(); - while ($q = new CGI::Fast) { - &process_request($q); - } - -Each time there's a new request, CGI::Fast returns a -CGI object to your loop. The rest of the time your script -waits in the call to new(). When the server requests that -your script be terminated, new() will return undef. You can -of course exit earlier if you choose. A new version of the -script will be respawned to take its place (this may be -necessary in order to avoid Perl memory leaks in long-running -scripts). - -CGI.pm's default CGI object mode also works. Just modify the loop -this way: - - while (new CGI::Fast) { - &process_request; - } - -Calls to header(), start_form(), etc. will all operate on the -current request. - -=head1 INSTALLING FASTCGI SCRIPTS - -See the FastCGI developer's kit documentation for full details. On -the Apache server, the following line must be added to srm.conf: - - AddType application/x-httpd-fcgi .fcgi - -FastCGI scripts must end in the extension .fcgi. For each script you -install, you must add something like the following to srm.conf: - - FastCgiServer /usr/etc/httpd/fcgi-bin/file_upload.fcgi -processes 2 - -This instructs Apache to launch two copies of file_upload.fcgi at -startup time. - -=head1 USING FASTCGI SCRIPTS AS CGI SCRIPTS - -Any script that works correctly as a FastCGI script will also work -correctly when installed as a vanilla CGI script. However it will -not see any performance benefit. - -=head1 EXTERNAL FASTCGI SERVER INVOCATION - -FastCGI supports a TCP/IP transport mechanism which allows FastCGI scripts to run -external to the webserver, perhaps on a remote machine. To configure the -webserver to connect to an external FastCGI server, you would add the following -to your srm.conf: - - FastCgiExternalServer /usr/etc/httpd/fcgi-bin/file_upload.fcgi -host sputnik:8888 - -Two environment variables affect how the C<CGI::Fast> object is created, -allowing C<CGI::Fast> to be used as an external FastCGI server. (See C<FCGI> -documentation for C<FCGI::OpenSocket> for more information.) - -=over - -=item FCGI_SOCKET_PATH - -The address (TCP/IP) or path (UNIX Domain) of the socket the external FastCGI -script to which bind an listen for incoming connections from the web server. - -=item FCGI_LISTEN_QUEUE - -Maximum length of the queue of pending connections. - -=back - -For example: - - #!/usr/local/bin/perl # must be a FastCGI version of perl! - use CGI::Fast; - &do_some_initialization(); - $ENV{FCGI_SOCKET_PATH} = "sputnik:8888"; - $ENV{FCGI_LISTEN_QUEUE} = 100; - while ($q = new CGI::Fast) { - &process_request($q); - } - -=head1 CAVEATS - -I haven't tested this very much. - -=head1 AUTHOR INFORMATION - -Copyright 1996-1998, Lincoln D. Stein. All rights reserved. - -This library is free software; you can redistribute it and/or modify -it under the same terms as Perl itself. - -Address bug reports and comments to: lstein@cshl.org - -=head1 BUGS - -This section intentionally left blank. - -=head1 SEE ALSO - -L<CGI::Carp>, L<CGI> - -=cut diff --git a/ext/CGI/lib/CGI/Pretty.pm b/ext/CGI/lib/CGI/Pretty.pm deleted file mode 100644 index 83d5a585be..0000000000 --- a/ext/CGI/lib/CGI/Pretty.pm +++ /dev/null @@ -1,308 +0,0 @@ -package CGI::Pretty; - -# See the bottom of this file for the POD documentation. Search for the -# string '=head'. - -# You can run this file through either pod2man or pod2html to produce pretty -# documentation in manual or html file format (these utilities are part of the -# Perl 5 distribution). - -use strict; -use CGI (); - -$CGI::Pretty::VERSION = '3.44'; -$CGI::DefaultClass = __PACKAGE__; -$CGI::Pretty::AutoloadClass = 'CGI'; -@CGI::Pretty::ISA = qw( CGI ); - -initialize_globals(); - -sub _prettyPrint { - my $input = shift; - return if !$$input; - return if !$CGI::Pretty::LINEBREAK || !$CGI::Pretty::INDENT; - -# print STDERR "'", $$input, "'\n"; - - foreach my $i ( @CGI::Pretty::AS_IS ) { - if ( $$input =~ m{</$i>}si ) { - my ( $a, $b, $c ) = $$input =~ m{(.*)(<$i[\s/>].*?</$i>)(.*)}si; - next if !$b; - $a ||= ""; - $c ||= ""; - - _prettyPrint( \$a ) if $a; - _prettyPrint( \$c ) if $c; - - $b ||= ""; - $$input = "$a$b$c"; - return; - } - } - $$input =~ s/$CGI::Pretty::LINEBREAK/$CGI::Pretty::LINEBREAK$CGI::Pretty::INDENT/g; -} - -sub comment { - my($self,@p) = CGI::self_or_CGI(@_); - - my $s = "@p"; - $s =~ s/$CGI::Pretty::LINEBREAK/$CGI::Pretty::LINEBREAK$CGI::Pretty::INDENT/g if $CGI::Pretty::LINEBREAK; - - return $self->SUPER::comment( "$CGI::Pretty::LINEBREAK$CGI::Pretty::INDENT$s$CGI::Pretty::LINEBREAK" ) . $CGI::Pretty::LINEBREAK; -} - -sub _make_tag_func { - my ($self,$tagname) = @_; - - # As Lincoln as noted, the last else clause is VERY hairy, and it - # took me a while to figure out what I was trying to do. - # What it does is look for tags that shouldn't be indented (e.g. PRE) - # and makes sure that when we nest tags, those tags don't get - # indented. - # For an example, try print td( pre( "hello\nworld" ) ); - # If we didn't care about stuff like that, the code would be - # MUCH simpler. BTW: I won't claim to be a regular expression - # guru, so if anybody wants to contribute something that would - # be quicker, easier to read, etc, I would be more than - # willing to put it in - Brian - - my $func = qq" - sub $tagname {"; - - $func .= q' - shift if $_[0] && - (ref($_[0]) && - (substr(ref($_[0]),0,3) eq "CGI" || - UNIVERSAL::isa($_[0],"CGI"))); - my($attr) = ""; - if (ref($_[0]) && ref($_[0]) eq "HASH") { - my(@attr) = make_attributes(shift()||undef,1); - $attr = " @attr" if @attr; - }'; - - if ($tagname=~/start_(\w+)/i) { - $func .= qq! - return "<\L$1\E\$attr>\$CGI::Pretty::LINEBREAK";} !; - } elsif ($tagname=~/end_(\w+)/i) { - $func .= qq! - return "<\L/$1\E>\$CGI::Pretty::LINEBREAK"; } !; - } else { - $func .= qq# - return ( \$CGI::XHTML ? "<\L$tagname\E\$attr />" : "<\L$tagname\E\$attr>" ) . - \$CGI::Pretty::LINEBREAK unless \@_; - my(\$tag,\$untag) = ("<\L$tagname\E\$attr>","</\L$tagname>\E"); - - my \%ASIS = map { lc("\$_") => 1 } \@CGI::Pretty::AS_IS; - my \@args; - if ( \$CGI::Pretty::LINEBREAK || \$CGI::Pretty::INDENT ) { - if(ref(\$_[0]) eq 'ARRAY') { - \@args = \@{\$_[0]} - } else { - foreach (\@_) { - \$args[0] .= \$_; - \$args[0] .= \$CGI::Pretty::LINEBREAK if \$args[0] !~ /\$CGI::Pretty::LINEBREAK\$/ && 0; - chomp \$args[0] if exists \$ASIS{ "\L$tagname\E" }; - - \$args[0] .= \$" if \$args[0] !~ /\$CGI::Pretty::LINEBREAK\$/ && 1; - } - chop \$args[0] unless \$" eq ""; - } - } - else { - \@args = ref(\$_[0]) eq 'ARRAY' ? \@{\$_[0]} : "\@_"; - } - - my \@result; - if ( exists \$ASIS{ "\L$tagname\E" } ) { - \@result = map { "\$tag\$_\$untag\$CGI::Pretty::LINEBREAK" } - \@args; - } - else { - \@result = map { - chomp; - my \$tmp = \$_; - CGI::Pretty::_prettyPrint( \\\$tmp ); - \$tag . \$CGI::Pretty::LINEBREAK . - \$CGI::Pretty::INDENT . \$tmp . \$CGI::Pretty::LINEBREAK . - \$untag . \$CGI::Pretty::LINEBREAK - } \@args; - } - if (\$CGI::Pretty::LINEBREAK || \$CGI::Pretty::INDENT) { - return join ("", \@result); - } else { - return "\@result"; - } - }#; - } - - return $func; -} - -sub start_html { - return CGI::start_html( @_ ) . $CGI::Pretty::LINEBREAK; -} - -sub end_html { - return CGI::end_html( @_ ) . $CGI::Pretty::LINEBREAK; -} - -sub new { - my $class = shift; - my $this = $class->SUPER::new( @_ ); - - if ($CGI::MOD_PERL) { - if ($CGI::MOD_PERL == 1) { - my $r = Apache->request; - $r->register_cleanup(\&CGI::Pretty::_reset_globals); - } - else { - my $r = Apache2::RequestUtil->request; - $r->pool->cleanup_register(\&CGI::Pretty::_reset_globals); - } - } - $class->_reset_globals if $CGI::PERLEX; - - return bless $this, $class; -} - -sub initialize_globals { - # This is the string used for indentation of tags - $CGI::Pretty::INDENT = "\t"; - - # This is the string used for seperation between tags - $CGI::Pretty::LINEBREAK = $/; - - # These tags are not prettify'd. - @CGI::Pretty::AS_IS = qw( a pre code script textarea td ); - - 1; -} -sub _reset_globals { initialize_globals(); } - -# ugly, but quick fix -sub import { - my $self = shift; - no strict 'refs'; - ${ "$self\::AutoloadClass" } = 'CGI'; - - # This causes modules to clash. - undef %CGI::EXPORT; - undef %CGI::EXPORT; - - $self->_setup_symbols(@_); - my ($callpack, $callfile, $callline) = caller; - - # To allow overriding, search through the packages - # Till we find one in which the correct subroutine is defined. - my @packages = ($self,@{"$self\:\:ISA"}); - foreach my $sym (keys %CGI::EXPORT) { - my $pck; - my $def = ${"$self\:\:AutoloadClass"} || $CGI::DefaultClass; - foreach $pck (@packages) { - if (defined(&{"$pck\:\:$sym"})) { - $def = $pck; - last; - } - } - *{"${callpack}::$sym"} = \&{"$def\:\:$sym"}; - } -} - -1; - -=head1 NAME - -CGI::Pretty - module to produce nicely formatted HTML code - -=head1 SYNOPSIS - - use CGI::Pretty qw( :html3 ); - - # Print a table with a single data element - print table( TR( td( "foo" ) ) ); - -=head1 DESCRIPTION - -CGI::Pretty is a module that derives from CGI. It's sole function is to -allow users of CGI to output nicely formatted HTML code. - -When using the CGI module, the following code: - print table( TR( td( "foo" ) ) ); - -produces the following output: - <TABLE><TR><TD>foo</TD></TR></TABLE> - -If a user were to create a table consisting of many rows and many columns, -the resultant HTML code would be quite difficult to read since it has no -carriage returns or indentation. - -CGI::Pretty fixes this problem. What it does is add a carriage -return and indentation to the HTML code so that one can easily read -it. - - print table( TR( td( "foo" ) ) ); - -now produces the following output: - <TABLE> - <TR> - <TD> - foo - </TD> - </TR> - </TABLE> - - -=head2 Tags that won't be formatted - -The <A> and <PRE> tags are not formatted. If these tags were formatted, the -user would see the extra indentation on the web browser causing the page to -look different than what would be expected. If you wish to add more tags to -the list of tags that are not to be touched, push them onto the C<@AS_IS> array: - - push @CGI::Pretty::AS_IS,qw(CODE XMP); - -=head2 Customizing the Indenting - -If you wish to have your own personal style of indenting, you can change the -C<$INDENT> variable: - - $CGI::Pretty::INDENT = "\t\t"; - -would cause the indents to be two tabs. - -Similarly, if you wish to have more space between lines, you may change the -C<$LINEBREAK> variable: - - $CGI::Pretty::LINEBREAK = "\n\n"; - -would create two carriage returns between lines. - -If you decide you want to use the regular CGI indenting, you can easily do -the following: - - $CGI::Pretty::INDENT = $CGI::Pretty::LINEBREAK = ""; - -=head1 BUGS - -This section intentionally left blank. - -=head1 AUTHOR - -Brian Paulsen <Brian@ThePaulsens.com>, with minor modifications by -Lincoln Stein <lstein@cshl.org> for incorporation into the CGI.pm -distribution. - -Copyright 1999, Brian Paulsen. All rights reserved. - -This library is free software; you can redistribute it and/or modify -it under the same terms as Perl itself. - -Bug reports and comments to Brian@ThePaulsens.com. You can also write -to lstein@cshl.org, but this code looks pretty hairy to me and I'm not -sure I understand it! - -=head1 SEE ALSO - -L<CGI> - -=cut diff --git a/ext/CGI/lib/CGI/Push.pm b/ext/CGI/lib/CGI/Push.pm deleted file mode 100644 index 9e72abda55..0000000000 --- a/ext/CGI/lib/CGI/Push.pm +++ /dev/null @@ -1,325 +0,0 @@ -package CGI::Push; - -# See the bottom of this file for the POD documentation. Search for the -# string '=head'. - -# You can run this file through either pod2man or pod2html to produce pretty -# documentation in manual or html file format (these utilities are part of the -# Perl 5 distribution). - -# Copyright 1995-2000, Lincoln D. Stein. All rights reserved. -# It may be used and modified freely, but I do request that this copyright -# notice remain attached to the file. You may modify this module as you -# wish, but if you redistribute a modified version, please attach a note -# listing the modifications you have made. - -# The most recent version and complete docs are available at: -# http://stein.cshl.org/WWW/software/CGI/ - -$CGI::Push::VERSION='1.04'; -use CGI; -use CGI::Util 'rearrange'; -@ISA = ('CGI'); - -$CGI::DefaultClass = 'CGI::Push'; -$CGI::Push::AutoloadClass = 'CGI'; - -# add do_push() and push_delay() to exported tags -push(@{$CGI::EXPORT_TAGS{':standard'}},'do_push','push_delay'); - -sub do_push { - my ($self,@p) = CGI::self_or_default(@_); - - # unbuffer output - $| = 1; - srand; - my ($random) = sprintf("%08.0f",rand()*1E8); - my ($boundary) = "----=_NeXtPaRt$random"; - - my (@header); - my ($type,$callback,$delay,$last_page,$cookie,$target,$expires,$nph,@other) = rearrange([TYPE,NEXT_PAGE,DELAY,LAST_PAGE,[COOKIE,COOKIES],TARGET,EXPIRES,NPH],@p); - $type = 'text/html' unless $type; - $callback = \&simple_counter unless $callback && ref($callback) eq 'CODE'; - $delay = 1 unless defined($delay); - $self->push_delay($delay); - $nph = 1 unless defined($nph); - - my(@o); - foreach (@other) { push(@o,split("=")); } - push(@o,'-Target'=>$target) if defined($target); - push(@o,'-Cookie'=>$cookie) if defined($cookie); - push(@o,'-Type'=>"multipart/x-mixed-replace;boundary=\"$boundary\""); - push(@o,'-Server'=>"CGI.pm Push Module") if $nph; - push(@o,'-Status'=>'200 OK'); - push(@o,'-nph'=>1) if $nph; - print $self->header(@o); - - $boundary = "$CGI::CRLF--$boundary"; - - print "WARNING: YOUR BROWSER DOESN'T SUPPORT THIS SERVER-PUSH TECHNOLOGY.${boundary}$CGI::CRLF"; - - my (@contents) = &$callback($self,++$COUNTER); - - # now we enter a little loop - while (1) { - print "Content-type: ${type}$CGI::CRLF$CGI::CRLF" unless $type =~ /^dynamic|heterogeneous$/i; - print @contents; - @contents = &$callback($self,++$COUNTER); - if ((@contents) && defined($contents[0])) { - print "${boundary}$CGI::CRLF"; - do_sleep($self->push_delay()) if $self->push_delay(); - } else { - if ($last_page && ref($last_page) eq 'CODE') { - print "${boundary}$CGI::CRLF"; - do_sleep($self->push_delay()) if $self->push_delay(); - print "Content-type: ${type}$CGI::CRLF$CGI::CRLF" unless $type =~ /^dynamic|heterogeneous$/i; - print &$last_page($self,$COUNTER); - } - print "${boundary}--$CGI::CRLF"; - last; - } - } - print "WARNING: YOUR BROWSER DOESN'T SUPPORT THIS SERVER-PUSH TECHNOLOGY.$CGI::CRLF"; -} - -sub simple_counter { - my ($self,$count) = @_; - return $self->start_html("CGI::Push Default Counter"), - $self->h1("CGI::Push Default Counter"), - "This page has been updated ",$self->strong($count)," times.", - $self->hr(), - $self->a({'-href'=>'http://www.genome.wi.mit.edu/ftp/pub/software/WWW/cgi_docs.html'},'CGI.pm home page'), - $self->end_html; -} - -sub do_sleep { - my $delay = shift; - if ( ($delay >= 1) && ($delay!~/\./) ){ - sleep($delay); - } else { - select(undef,undef,undef,$delay); - } -} - -sub push_delay { - my ($self,$delay) = CGI::self_or_default(@_); - return defined($delay) ? $self->{'.delay'} = - $delay : $self->{'.delay'}; -} - -1; - -=head1 NAME - -CGI::Push - Simple Interface to Server Push - -=head1 SYNOPSIS - - use CGI::Push qw(:standard); - - do_push(-next_page=>\&next_page, - -last_page=>\&last_page, - -delay=>0.5); - - sub next_page { - my($q,$counter) = @_; - return undef if $counter >= 10; - return start_html('Test'), - h1('Visible'),"\n", - "This page has been called ", strong($counter)," times", - end_html(); - } - - sub last_page { - my($q,$counter) = @_; - return start_html('Done'), - h1('Finished'), - strong($counter - 1),' iterations.', - end_html; - } - -=head1 DESCRIPTION - -CGI::Push is a subclass of the CGI object created by CGI.pm. It is -specialized for server push operations, which allow you to create -animated pages whose content changes at regular intervals. - -You provide CGI::Push with a pointer to a subroutine that will draw -one page. Every time your subroutine is called, it generates a new -page. The contents of the page will be transmitted to the browser -in such a way that it will replace what was there beforehand. The -technique will work with HTML pages as well as with graphics files, -allowing you to create animated GIFs. - -Only Netscape Navigator supports server push. Internet Explorer -browsers do not. - -=head1 USING CGI::Push - -CGI::Push adds one new method to the standard CGI suite, do_push(). -When you call this method, you pass it a reference to a subroutine -that is responsible for drawing each new page, an interval delay, and -an optional subroutine for drawing the last page. Other optional -parameters include most of those recognized by the CGI header() -method. - -You may call do_push() in the object oriented manner or not, as you -prefer: - - use CGI::Push; - $q = new CGI::Push; - $q->do_push(-next_page=>\&draw_a_page); - - -or- - - use CGI::Push qw(:standard); - do_push(-next_page=>\&draw_a_page); - -Parameters are as follows: - -=over 4 - -=item -next_page - - do_push(-next_page=>\&my_draw_routine); - -This required parameter points to a reference to a subroutine responsible for -drawing each new page. The subroutine should expect two parameters -consisting of the CGI object and a counter indicating the number -of times the subroutine has been called. It should return the -contents of the page as an B<array> of one or more items to print. -It can return a false value (or an empty array) in order to abort the -redrawing loop and print out the final page (if any) - - sub my_draw_routine { - my($q,$counter) = @_; - return undef if $counter > 100; - return start_html('testing'), - h1('testing'), - "This page called $counter times"; - } - -You are of course free to refer to create and use global variables -within your draw routine in order to achieve special effects. - -=item -last_page - -This optional parameter points to a reference to the subroutine -responsible for drawing the last page of the series. It is called -after the -next_page routine returns a false value. The subroutine -itself should have exactly the same calling conventions as the --next_page routine. - -=item -type - -This optional parameter indicates the content type of each page. It -defaults to "text/html". Normally the module assumes that each page -is of a homogenous MIME type. However if you provide either of the -magic values "heterogeneous" or "dynamic" (the latter provided for the -convenience of those who hate long parameter names), you can specify -the MIME type -- and other header fields -- on a per-page basis. See -"heterogeneous pages" for more details. - -=item -delay - -This indicates the delay, in seconds, between frames. Smaller delays -refresh the page faster. Fractional values are allowed. - -B<If not specified, -delay will default to 1 second> - -=item -cookie, -target, -expires, -nph - -These have the same meaning as the like-named parameters in -CGI::header(). - -If not specified, -nph will default to 1 (as needed for many servers, see below). - -=back - -=head2 Heterogeneous Pages - -Ordinarily all pages displayed by CGI::Push share a common MIME type. -However by providing a value of "heterogeneous" or "dynamic" in the -do_push() -type parameter, you can specify the MIME type of each page -on a case-by-case basis. - -If you use this option, you will be responsible for producing the -HTTP header for each page. Simply modify your draw routine to -look like this: - - sub my_draw_routine { - my($q,$counter) = @_; - return header('text/html'), # note we're producing the header here - start_html('testing'), - h1('testing'), - "This page called $counter times"; - } - -You can add any header fields that you like, but some (cookies and -status fields included) may not be interpreted by the browser. One -interesting effect is to display a series of pages, then, after the -last page, to redirect the browser to a new URL. Because redirect() -does b<not> work, the easiest way is with a -refresh header field, -as shown below: - - sub my_draw_routine { - my($q,$counter) = @_; - return undef if $counter > 10; - return header('text/html'), # note we're producing the header here - start_html('testing'), - h1('testing'), - "This page called $counter times"; - } - - sub my_last_page { - return header(-refresh=>'5; URL=http://somewhere.else/finished.html', - -type=>'text/html'), - start_html('Moved'), - h1('This is the last page'), - 'Goodbye!' - hr, - end_html; - } - -=head2 Changing the Page Delay on the Fly - -If you would like to control the delay between pages on a page-by-page -basis, call push_delay() from within your draw routine. push_delay() -takes a single numeric argument representing the number of seconds you -wish to delay after the current page is displayed and before -displaying the next one. The delay may be fractional. Without -parameters, push_delay() just returns the current delay. - -=head1 INSTALLING CGI::Push SCRIPTS - -Server push scripts must be installed as no-parsed-header (NPH) -scripts in order to work correctly on many servers. On Unix systems, -this is most often accomplished by prefixing the script's name with "nph-". -Recognition of NPH scripts happens automatically with WebSTAR and -Microsoft IIS. Users of other servers should see their documentation -for help. - -Apache web server from version 1.3b2 on does not need server -push scripts installed as NPH scripts: the -nph parameter to do_push() -may be set to a false value to disable the extra headers needed by an -NPH script. - -=head1 AUTHOR INFORMATION - -Copyright 1995-1998, Lincoln D. Stein. All rights reserved. - -This library is free software; you can redistribute it and/or modify -it under the same terms as Perl itself. - -Address bug reports and comments to: lstein@cshl.org - -=head1 BUGS - -This section intentionally left blank. - -=head1 SEE ALSO - -L<CGI::Carp>, L<CGI> - -=cut - diff --git a/ext/CGI/lib/CGI/Switch.pm b/ext/CGI/lib/CGI/Switch.pm deleted file mode 100644 index a311080e49..0000000000 --- a/ext/CGI/lib/CGI/Switch.pm +++ /dev/null @@ -1,28 +0,0 @@ -package CGI::Switch; -use CGI; - -$VERSION = '1.01'; - -1; - -__END__ - -=head1 NAME - -CGI::Switch - Backward compatibility module for defunct CGI::Switch - -=head1 SYNOPSIS - -Do not use this module. It is deprecated. - -=head1 ABSTRACT - -=head1 DESCRIPTION - -=head1 AUTHOR INFORMATION - -=head1 BUGS - -=head1 SEE ALSO - -=cut diff --git a/ext/CGI/lib/CGI/Util.pm b/ext/CGI/lib/CGI/Util.pm deleted file mode 100644 index 9a0ea2be93..0000000000 --- a/ext/CGI/lib/CGI/Util.pm +++ /dev/null @@ -1,365 +0,0 @@ -package CGI::Util; - -use strict; -use vars qw($VERSION @EXPORT_OK @ISA $EBCDIC @A2E @E2A); -require Exporter; -@ISA = qw(Exporter); -@EXPORT_OK = qw(rearrange rearrange_header make_attributes unescape escape - expires ebcdic2ascii ascii2ebcdic); - -$VERSION = '3.45'; - -$EBCDIC = "\t" ne "\011"; -# (ord('^') == 95) for codepage 1047 as on os390, vmesa -@A2E = ( - 0, 1, 2, 3, 55, 45, 46, 47, 22, 5, 21, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 60, 61, 50, 38, 24, 25, 63, 39, 28, 29, 30, 31, - 64, 90,127,123, 91,108, 80,125, 77, 93, 92, 78,107, 96, 75, 97, - 240,241,242,243,244,245,246,247,248,249,122, 94, 76,126,110,111, - 124,193,194,195,196,197,198,199,200,201,209,210,211,212,213,214, - 215,216,217,226,227,228,229,230,231,232,233,173,224,189, 95,109, - 121,129,130,131,132,133,134,135,136,137,145,146,147,148,149,150, - 151,152,153,162,163,164,165,166,167,168,169,192, 79,208,161, 7, - 32, 33, 34, 35, 36, 37, 6, 23, 40, 41, 42, 43, 44, 9, 10, 27, - 48, 49, 26, 51, 52, 53, 54, 8, 56, 57, 58, 59, 4, 20, 62,255, - 65,170, 74,177,159,178,106,181,187,180,154,138,176,202,175,188, - 144,143,234,250,190,160,182,179,157,218,155,139,183,184,185,171, - 100,101, 98,102, 99,103,158,104,116,113,114,115,120,117,118,119, - 172,105,237,238,235,239,236,191,128,253,254,251,252,186,174, 89, - 68, 69, 66, 70, 67, 71,156, 72, 84, 81, 82, 83, 88, 85, 86, 87, - 140, 73,205,206,203,207,204,225,112,221,222,219,220,141,142,223 - ); -@E2A = ( - 0, 1, 2, 3,156, 9,134,127,151,141,142, 11, 12, 13, 14, 15, - 16, 17, 18, 19,157, 10, 8,135, 24, 25,146,143, 28, 29, 30, 31, - 128,129,130,131,132,133, 23, 27,136,137,138,139,140, 5, 6, 7, - 144,145, 22,147,148,149,150, 4,152,153,154,155, 20, 21,158, 26, - 32,160,226,228,224,225,227,229,231,241,162, 46, 60, 40, 43,124, - 38,233,234,235,232,237,238,239,236,223, 33, 36, 42, 41, 59, 94, - 45, 47,194,196,192,193,195,197,199,209,166, 44, 37, 95, 62, 63, - 248,201,202,203,200,205,206,207,204, 96, 58, 35, 64, 39, 61, 34, - 216, 97, 98, 99,100,101,102,103,104,105,171,187,240,253,254,177, - 176,106,107,108,109,110,111,112,113,114,170,186,230,184,198,164, - 181,126,115,116,117,118,119,120,121,122,161,191,208, 91,222,174, - 172,163,165,183,169,167,182,188,189,190,221,168,175, 93,180,215, - 123, 65, 66, 67, 68, 69, 70, 71, 72, 73,173,244,246,242,243,245, - 125, 74, 75, 76, 77, 78, 79, 80, 81, 82,185,251,252,249,250,255, - 92,247, 83, 84, 85, 86, 87, 88, 89, 90,178,212,214,210,211,213, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,179,219,220,217,218,159 - ); - -if ($EBCDIC && ord('^') == 106) { # as in the BS2000 posix-bc coded character set - $A2E[91] = 187; $A2E[92] = 188; $A2E[94] = 106; $A2E[96] = 74; - $A2E[123] = 251; $A2E[125] = 253; $A2E[126] = 255; $A2E[159] = 95; - $A2E[162] = 176; $A2E[166] = 208; $A2E[168] = 121; $A2E[172] = 186; - $A2E[175] = 161; $A2E[217] = 224; $A2E[219] = 221; $A2E[221] = 173; - $A2E[249] = 192; - - $E2A[74] = 96; $E2A[95] = 159; $E2A[106] = 94; $E2A[121] = 168; - $E2A[161] = 175; $E2A[173] = 221; $E2A[176] = 162; $E2A[186] = 172; - $E2A[187] = 91; $E2A[188] = 92; $E2A[192] = 249; $E2A[208] = 166; - $E2A[221] = 219; $E2A[224] = 217; $E2A[251] = 123; $E2A[253] = 125; - $E2A[255] = 126; - } -elsif ($EBCDIC && ord('^') == 176) { # as in codepage 037 on os400 - $A2E[10] = 37; $A2E[91] = 186; $A2E[93] = 187; $A2E[94] = 176; - $A2E[133] = 21; $A2E[168] = 189; $A2E[172] = 95; $A2E[221] = 173; - - $E2A[21] = 133; $E2A[37] = 10; $E2A[95] = 172; $E2A[173] = 221; - $E2A[176] = 94; $E2A[186] = 91; $E2A[187] = 93; $E2A[189] = 168; -} - -# Smart rearrangement of parameters to allow named parameter -# calling. We do the rearrangement if: -# the first parameter begins with a - - -sub rearrange { - my ($order,@param) = @_; - my ($result, $leftover) = _rearrange_params( $order, @param ); - push @$result, make_attributes( $leftover, defined $CGI::Q ? $CGI::Q->{escape} : 1 ) - if keys %$leftover; - @$result; -} - -sub rearrange_header { - my ($order,@param) = @_; - - my ($result,$leftover) = _rearrange_params( $order, @param ); - push @$result, make_attributes( $leftover, 0, 1 ) if keys %$leftover; - - @$result; -} - -sub _rearrange_params { - my($order,@param) = @_; - return [] unless @param; - - if (ref($param[0]) eq 'HASH') { - @param = %{$param[0]}; - } else { - return \@param - unless (defined($param[0]) && substr($param[0],0,1) eq '-'); - } - - # map parameters into positional indices - my ($i,%pos); - $i = 0; - foreach (@$order) { - foreach (ref($_) eq 'ARRAY' ? @$_ : $_) { $pos{lc($_)} = $i; } - $i++; - } - - my (@result,%leftover); - $#result = $#$order; # preextend - while (@param) { - my $key = lc(shift(@param)); - $key =~ s/^\-//; - if (exists $pos{$key}) { - $result[$pos{$key}] = shift(@param); - } else { - $leftover{$key} = shift(@param); - } - } - - return \@result, \%leftover; -} - -sub make_attributes { - my $attr = shift; - return () unless $attr && ref($attr) && ref($attr) eq 'HASH'; - my $escape = shift || 0; - my $do_not_quote = shift; - - my $quote = $do_not_quote ? '' : '"'; - - my(@att); - foreach (keys %{$attr}) { - my($key) = $_; - $key=~s/^\-//; # get rid of initial - if present - - # old way: breaks EBCDIC! - # $key=~tr/A-Z_/a-z-/; # parameters are lower case, use dashes - - ($key="\L$key") =~ tr/_/-/; # parameters are lower case, use dashes - - my $value = $escape ? simple_escape($attr->{$_}) : $attr->{$_}; - push(@att,defined($attr->{$_}) ? qq/$key=$quote$value$quote/ : qq/$key/); - } - return @att; -} - -sub simple_escape { - return unless defined(my $toencode = shift); - $toencode =~ s{&}{&}gso; - $toencode =~ s{<}{<}gso; - $toencode =~ s{>}{>}gso; - $toencode =~ s{\"}{"}gso; -# Doesn't work. Can't work. forget it. -# $toencode =~ s{\x8b}{‹}gso; -# $toencode =~ s{\x9b}{›}gso; - $toencode; -} - -sub utf8_chr { - my $c = shift(@_); - if ($] >= 5.006){ - require utf8; - my $u = chr($c); - utf8::encode($u); # drop utf8 flag - return $u; - } - if ($c < 0x80) { - return sprintf("%c", $c); - } elsif ($c < 0x800) { - return sprintf("%c%c", 0xc0 | ($c >> 6), 0x80 | ($c & 0x3f)); - } elsif ($c < 0x10000) { - return sprintf("%c%c%c", - 0xe0 | ($c >> 12), - 0x80 | (($c >> 6) & 0x3f), - 0x80 | ( $c & 0x3f)); - } elsif ($c < 0x200000) { - return sprintf("%c%c%c%c", - 0xf0 | ($c >> 18), - 0x80 | (($c >> 12) & 0x3f), - 0x80 | (($c >> 6) & 0x3f), - 0x80 | ( $c & 0x3f)); - } elsif ($c < 0x4000000) { - return sprintf("%c%c%c%c%c", - 0xf8 | ($c >> 24), - 0x80 | (($c >> 18) & 0x3f), - 0x80 | (($c >> 12) & 0x3f), - 0x80 | (($c >> 6) & 0x3f), - 0x80 | ( $c & 0x3f)); - - } elsif ($c < 0x80000000) { - return sprintf("%c%c%c%c%c%c", - 0xfc | ($c >> 30), - 0x80 | (($c >> 24) & 0x3f), - 0x80 | (($c >> 18) & 0x3f), - 0x80 | (($c >> 12) & 0x3f), - 0x80 | (($c >> 6) & 0x3f), - 0x80 | ( $c & 0x3f)); - } else { - return utf8_chr(0xfffd); - } -} - -# unescape URL-encoded data -sub unescape { - shift() if @_ > 0 and (ref($_[0]) || (defined $_[1] && $_[0] eq $CGI::DefaultClass)); - my $todecode = shift; - return undef unless defined($todecode); - $todecode =~ tr/+/ /; # pluses become spaces - if ($EBCDIC) { - $todecode =~ s/%([0-9a-fA-F]{2})/chr $A2E[hex($1)]/ge; - } else { - # handle surrogate pairs first -- dankogai - $todecode =~ s{ - %u([Dd][89a-bA-B][0-9a-fA-F]{2}) # hi - %u([Dd][c-fC-F][0-9a-fA-F]{2}) # lo - }{ - utf8_chr( - 0x10000 - + (hex($1) - 0xD800) * 0x400 - + (hex($2) - 0xDC00) - ) - }gex; - $todecode =~ s/%(?:([0-9a-fA-F]{2})|u([0-9a-fA-F]{4}))/ - defined($1)? chr hex($1) : utf8_chr(hex($2))/ge; - } - return $todecode; -} - -# URL-encode data -# -# We cannot use the %u escapes, they were rejected by W3C, so the official -# way is %XX-escaped utf-8 encoding. -# Naturally, Unicode strings have to be converted to their utf-8 byte -# representation. (No action is required on 5.6.) -# Byte strings were traditionally used directly as a sequence of octets. -# This worked if they actually represented binary data (i.e. in CGI::Compress). -# This also worked if these byte strings were actually utf-8 encoded; e.g., -# when the source file used utf-8 without the apropriate "use utf8;". -# This fails if the byte string is actually a Latin 1 encoded string, but it -# was always so and cannot be fixed without breaking the binary data case. -# -- Stepan Kasal <skasal@redhat.com> -# -sub escape { - shift() if @_ > 1 and ( ref($_[0]) || (defined $_[1] && $_[0] eq $CGI::DefaultClass)); - my $toencode = shift; - return undef unless defined($toencode); - utf8::encode($toencode) if ($] > 5.007 && utf8::is_utf8($toencode)); - if ($EBCDIC) { - $toencode=~s/([^a-zA-Z0-9_.~-])/uc sprintf("%%%02x",$E2A[ord($1)])/eg; - } else { - $toencode=~s/([^a-zA-Z0-9_.~-])/uc sprintf("%%%02x",ord($1))/eg; - } - return $toencode; -} - -# This internal routine creates date strings suitable for use in -# cookies and HTTP headers. (They differ, unfortunately.) -# Thanks to Mark Fisher for this. -sub expires { - my($time,$format) = @_; - $format ||= 'http'; - - my(@MON)=qw/Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec/; - my(@WDAY) = qw/Sun Mon Tue Wed Thu Fri Sat/; - - # pass through preformatted dates for the sake of expire_calc() - $time = expire_calc($time); - return $time unless $time =~ /^\d+$/; - - # make HTTP/cookie date string from GMT'ed time - # (cookies use '-' as date separator, HTTP uses ' ') - my($sc) = ' '; - $sc = '-' if $format eq "cookie"; - my($sec,$min,$hour,$mday,$mon,$year,$wday) = gmtime($time); - $year += 1900; - return sprintf("%s, %02d$sc%s$sc%04d %02d:%02d:%02d GMT", - $WDAY[$wday],$mday,$MON[$mon],$year,$hour,$min,$sec); -} - -# This internal routine creates an expires time exactly some number of -# hours from the current time. It incorporates modifications from -# Mark Fisher. -sub expire_calc { - my($time) = @_; - my(%mult) = ('s'=>1, - 'm'=>60, - 'h'=>60*60, - 'd'=>60*60*24, - 'M'=>60*60*24*30, - 'y'=>60*60*24*365); - # format for time can be in any of the forms... - # "now" -- expire immediately - # "+180s" -- in 180 seconds - # "+2m" -- in 2 minutes - # "+12h" -- in 12 hours - # "+1d" -- in 1 day - # "+3M" -- in 3 months - # "+2y" -- in 2 years - # "-3m" -- 3 minutes ago(!) - # If you don't supply one of these forms, we assume you are - # specifying the date yourself - my($offset); - if (!$time || (lc($time) eq 'now')) { - $offset = 0; - } elsif ($time=~/^\d+/) { - return $time; - } elsif ($time=~/^([+-]?(?:\d+|\d*\.\d*))([smhdMy])/) { - $offset = ($mult{$2} || 1)*$1; - } else { - return $time; - } - return (time+$offset); -} - -sub ebcdic2ascii { - my $data = shift; - $data =~ s/(.)/chr $E2A[ord($1)]/ge; - $data; -} - -sub ascii2ebcdic { - my $data = shift; - $data =~ s/(.)/chr $A2E[ord($1)]/ge; - $data; -} - -1; - -__END__ - -=head1 NAME - -CGI::Util - Internal utilities used by CGI module - -=head1 SYNOPSIS - -none - -=head1 DESCRIPTION - -no public subroutines - -=head1 AUTHOR INFORMATION - -Copyright 1995-1998, Lincoln D. Stein. All rights reserved. - -This library is free software; you can redistribute it and/or modify -it under the same terms as Perl itself. - -Address bug reports and comments to: lstein@cshl.org. When sending -bug reports, please provide the version of CGI.pm, the version of -Perl, the name and version of your Web server, and the name and -version of the operating system you are using. If the problem is even -remotely browser dependent, please provide information about the -affected browers as well. - -=head1 SEE ALSO - -L<CGI> - -=cut diff --git a/ext/CGI/t/Dump.t b/ext/CGI/t/Dump.t deleted file mode 100644 index fafb5b22eb..0000000000 --- a/ext/CGI/t/Dump.t +++ /dev/null @@ -1,5 +0,0 @@ -use Test::More 'no_plan'; -use CGI; -my $cgi = CGI->new('<a>=<b>'); -like($cgi->Dump, qr/\Q<a>/, 'param names are HTML escaped by Dump()'); -like($cgi->Dump, qr/\Q<b>/, 'param values are HTML escaped by Dump()'); diff --git a/ext/CGI/t/apache.t b/ext/CGI/t/apache.t deleted file mode 100644 index 7f92155c3f..0000000000 --- a/ext/CGI/t/apache.t +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/local/bin/perl -w - -use lib qw(t/lib); - -# Due to a bug in older versions of MakeMaker & Test::Harness, we must -# ensure the blib's are in @INC, else we might use the core CGI.pm -use lib qw(blib/lib blib/arch); - -use strict; -use Test::More tests => 1; - -# Can't do much with this other than make sure it loads properly -BEGIN { use_ok('CGI::Apache') }; diff --git a/ext/CGI/t/can.t b/ext/CGI/t/can.t deleted file mode 100644 index 720eb493e8..0000000000 --- a/ext/CGI/t/can.t +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/local/bin/perl -w - -# Due to a bug in older versions of MakeMaker & Test::Harness, we must -# ensure the blib's are in @INC, else we might use the core CGI.pm - -use lib qw(blib/lib blib/arch); - -use Test::More tests => 2; - -BEGIN{ use_ok('CGI'); } - -can_ok('CGI', qw/cookie param/);
\ No newline at end of file diff --git a/ext/CGI/t/carp.t b/ext/CGI/t/carp.t deleted file mode 100644 index 6d20a4fe9d..0000000000 --- a/ext/CGI/t/carp.t +++ /dev/null @@ -1,280 +0,0 @@ -# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 2 -*- -#!/usr/local/bin/perl -w - -use strict; -use lib qw(t/lib); - -# Due to a bug in older versions of MakeMaker & Test::Harness, we must -# ensure the blib's are in @INC, else we might use the core CGI.pm -use lib qw(blib/lib blib/arch); - -use Test::More tests => 41; -use IO::Handle; - -BEGIN { use_ok('CGI::Carp') }; - -#----------------------------------------------------------------------------- -# Test id -#----------------------------------------------------------------------------- - -# directly invoked -my $expect_f = __FILE__; -my $expect_l = __LINE__ + 1; -my ($file, $line, $id) = CGI::Carp::id(0); -is($file, $expect_f, "file"); -is($line, $expect_l, "line"); -is($id, "carp.t", "id"); - -# one level of indirection -sub id1 { my $level = shift; return CGI::Carp::id($level); }; - -$expect_l = __LINE__ + 1; -($file, $line, $id) = id1(1); -is($file, $expect_f, "file"); -is($line, $expect_l, "line"); -is($id, "carp.t", "id"); - -# two levels of indirection -sub id2 { my $level = shift; return id1($level); }; - -$expect_l = __LINE__ + 1; -($file, $line, $id) = id2(2); -is($file, $expect_f, "file"); -is($line, $expect_l, "line"); -is($id, "carp.t", "id"); - -#----------------------------------------------------------------------------- -# Test stamp -#----------------------------------------------------------------------------- - -my $stamp = "/^\\[ - ([a-z]{3}\\s){2}\\s? - [\\s\\d:]+ - \\]\\s$id:/ix"; - -like(CGI::Carp::stamp(), - $stamp, - "Time in correct format"); - -sub stamp1 {return CGI::Carp::stamp()}; -sub stamp2 {return stamp1()}; - -like(stamp2(), $stamp, "Time in correct format"); - -#----------------------------------------------------------------------------- -# Test warn and _warn -#----------------------------------------------------------------------------- - -# set some variables to control what's going on. -$CGI::Carp::WARN = 0; -$CGI::Carp::EMIT_WARNINGS = 0; -my $q_file = quotemeta($file); - - -# Test that realwarn is called -{ - local $^W = 0; - eval "sub CGI::Carp::realwarn {return 'Called realwarn'};"; -} - -$expect_l = __LINE__ + 1; -is(CGI::Carp::warn("There is a problem"), - "Called realwarn", - "CGI::Carp::warn calls CORE::warn"); - -# Test that message is constructed correctly -eval 'sub CGI::Carp::realwarn {my $mess = shift; return $mess};'; - -$expect_l = __LINE__ + 1; -like(CGI::Carp::warn("There is a problem"), - "/] $id: There is a problem at $q_file line $expect_l.".'$/', - "CGI::Carp::warn builds correct message"); - -# Test that _warn is called at the correct time -$CGI::Carp::WARN = 1; - -my $warn_expect_l = $expect_l = __LINE__ + 1; -like(CGI::Carp::warn("There is a problem"), - "/] $id: There is a problem at $q_file line $expect_l.".'$/', - "CGI::Carp::warn builds correct message"); - -#----------------------------------------------------------------------------- -# Test ineval -#----------------------------------------------------------------------------- - -ok(!CGI::Carp::ineval, 'ineval returns false when not in eval'); -eval {ok(CGI::Carp::ineval, 'ineval returns true when in eval');}; - -#----------------------------------------------------------------------------- -# Test die -#----------------------------------------------------------------------------- - -# set some variables to control what's going on. -$CGI::Carp::WRAP = 0; - -$expect_l = __LINE__ + 1; -eval { CGI::Carp::die('There is a problem'); }; -like($@, - '/^There is a problem/', - 'CGI::Carp::die calls CORE::die without altering argument in eval'); - -# Test that realwarn is called -{ - local $^W = 0; - eval 'sub CGI::Carp::realdie {my $mess = shift; return $mess};'; -} - -like(CGI::Carp::die('There is a problem'), - $stamp, - 'CGI::Carp::die calls CORE::die, but adds stamp'); - -#----------------------------------------------------------------------------- -# Test set_message -#----------------------------------------------------------------------------- - -is(CGI::Carp::set_message('My new Message'), - 'My new Message', - 'CGI::Carp::set_message returns new message'); - -is($CGI::Carp::CUSTOM_MSG, - 'My new Message', - 'CGI::Carp::set_message message set correctly'); - -# set the message back to the empty string so that the tests later -# work properly. -CGI::Carp::set_message(''), - -#----------------------------------------------------------------------------- -# Test set_progname -#----------------------------------------------------------------------------- - -import CGI::Carp qw(name=new_progname); -is($CGI::Carp::PROGNAME, - 'new_progname', - 'CGI::Carp::import set program name correctly'); - -is(CGI::Carp::set_progname('newer_progname'), - 'newer_progname', - 'CGI::Carp::set_progname returns new program name'); - -is($CGI::Carp::PROGNAME, - 'newer_progname', - 'CGI::Carp::set_progname program name set correctly'); - -# set the message back to the empty string so that the tests later -# work properly. -is (CGI::Carp::set_progname(undef),undef,"CGI::Carp::set_progname returns unset name correctly"); -is ($CGI::Carp::PROGNAME,undef,"CGI::Carp::set_progname program name unset correctly"); - -#----------------------------------------------------------------------------- -# Test warnings_to_browser -#----------------------------------------------------------------------------- - -CGI::Carp::warningsToBrowser(0); -is($CGI::Carp::EMIT_WARNINGS, 0, "Warnings turned off"); - -# turn off STDOUT (prevents spurious warnings to screen -tie *STDOUT, 'StoreStuff' or die "Can't tie STDOUT"; -CGI::Carp::warningsToBrowser(1); -my $fake_out = join '', <STDOUT>; -untie *STDOUT; - -open(STDOUT, ">&REAL_STDOUT"); -my $fname = $0; -$fname =~ tr/<>-/\253\273\255/; # _warn does this so we have to also -is( $fake_out, "<!-- warning: There is a problem at $fname line $warn_expect_l. -->\n", - 'warningsToBrowser() on' ); - -is($CGI::Carp::EMIT_WARNINGS, 1, "Warnings turned off"); - -#----------------------------------------------------------------------------- -# Test fatals_to_browser -#----------------------------------------------------------------------------- - -package StoreStuff; - -sub TIEHANDLE { - my $class = shift; - bless [], $class; -} - -sub PRINT { - my $self = shift; - push @$self, @_; -} - -sub READLINE { - my $self = shift; - shift @$self; -} - -package main; - -tie *STDOUT, "StoreStuff"; - -# do tests -my @result; - -CGI::Carp::fatalsToBrowser(); -$result[0] .= $_ while (<STDOUT>); - -CGI::Carp::fatalsToBrowser('Message to the world'); -$result[1] .= $_ while (<STDOUT>); - -$ENV{SERVER_ADMIN} = 'foo@bar.com'; -CGI::Carp::fatalsToBrowser(); -$result[2] .= $_ while (<STDOUT>); - -CGI::Carp::set_message('Override the message passed in'), - -CGI::Carp::fatalsToBrowser('Message to the world'); -$result[3] .= $_ while (<STDOUT>); -CGI::Carp::set_message(''), -delete $ENV{SERVER_ADMIN}; - -# now restore STDOUT -untie *STDOUT; - - -like($result[0], - '/Content-type: text/html/', - "Default string has header"); - -ok($result[0] !~ /Message to the world/, "Custom message not in default string"); - -like($result[1], - '/Message to the world/', - "Custom Message appears in output"); - -ok($result[0] !~ /foo\@bar.com/, "Server Admin does not appear in default message"); - -like($result[2], - '/foo@bar.com/', - "Server Admin appears in output"); - -like($result[3], - '/Message to the world/', - "Custom message not in result"); - -like($result[3], - '/Override the message passed in/', - "Correct message in string"); - -#----------------------------------------------------------------------------- -# Test to_filehandle -#----------------------------------------------------------------------------- - -sub buffer { - CGI::Carp::to_filehandle (@_); -} - -tie *STORE, "StoreStuff"; - -require FileHandle; -my $fh = FileHandle->new; - -ok( defined buffer(\*STORE), '\*STORE returns proper filehandle'); -ok( defined buffer( $fh ), '$fh returns proper filehandle'); -ok( defined buffer('::STDOUT'), 'STDIN returns proper filehandle'); -ok( defined buffer(*main::STDOUT), 'STDIN returns proper filehandle'); -ok(!defined buffer("WIBBLE"), '"WIBBLE" doesn\'t returns proper filehandle'); diff --git a/ext/CGI/t/cookie.t b/ext/CGI/t/cookie.t deleted file mode 100644 index 539ac7a26e..0000000000 --- a/ext/CGI/t/cookie.t +++ /dev/null @@ -1,375 +0,0 @@ -#!/usr/local/bin/perl -w - -use lib qw(t/lib); -use strict; - -# Due to a bug in older versions of MakeMaker & Test::Harness, we must -# ensure the blib's are in @INC, else we might use the core CGI.pm -use lib qw(blib/lib blib/arch); - -use Test::More tests => 96; -use CGI::Util qw(escape unescape); -use POSIX qw(strftime); - -#----------------------------------------------------------------------------- -# make sure module loaded -#----------------------------------------------------------------------------- - -BEGIN {use_ok('CGI::Cookie');} - -my @test_cookie = ( - 'foo=123; bar=qwerty; baz=wibble; qux=a1', - 'foo=123; bar=qwerty; baz=wibble;', - 'foo=vixen; bar=cow; baz=bitch; qux=politician', - 'foo=a%20phrase; bar=yes%2C%20a%20phrase; baz=%5Ewibble; qux=%27', - ); - -#----------------------------------------------------------------------------- -# Test parse -#----------------------------------------------------------------------------- - -{ - my $result = CGI::Cookie->parse($test_cookie[0]); - - is(ref($result), 'HASH', "Hash ref returned in scalar context"); - - my @result = CGI::Cookie->parse($test_cookie[0]); - - is(@result, 8, "returns correct number of fields"); - - @result = CGI::Cookie->parse($test_cookie[1]); - - is(@result, 6, "returns correct number of fields"); - - my %result = CGI::Cookie->parse($test_cookie[0]); - - is($result{foo}->value, '123', "cookie foo is correct"); - is($result{bar}->value, 'qwerty', "cookie bar is correct"); - is($result{baz}->value, 'wibble', "cookie baz is correct"); - is($result{qux}->value, 'a1', "cookie qux is correct"); -} - -#----------------------------------------------------------------------------- -# Test fetch -#----------------------------------------------------------------------------- - -{ - # make sure there are no cookies in the environment - delete $ENV{HTTP_COOKIE}; - delete $ENV{COOKIE}; - - my %result = CGI::Cookie->fetch(); - ok(keys %result == 0, "No cookies in environment, returns empty list"); - - # now set a cookie in the environment and try again - $ENV{HTTP_COOKIE} = $test_cookie[2]; - %result = CGI::Cookie->fetch(); - ok(eq_set([keys %result], [qw(foo bar baz qux)]), - "expected cookies extracted"); - - is(ref($result{foo}), 'CGI::Cookie', 'Type of objects returned is correct'); - is($result{foo}->value, 'vixen', "cookie foo is correct"); - is($result{bar}->value, 'cow', "cookie bar is correct"); - is($result{baz}->value, 'bitch', "cookie baz is correct"); - is($result{qux}->value, 'politician', "cookie qux is correct"); - - # Delete that and make sure it goes away - delete $ENV{HTTP_COOKIE}; - %result = CGI::Cookie->fetch(); - ok(keys %result == 0, "No cookies in environment, returns empty list"); - - # try another cookie in the other environment variable thats supposed to work - $ENV{COOKIE} = $test_cookie[3]; - %result = CGI::Cookie->fetch(); - ok(eq_set([keys %result], [qw(foo bar baz qux)]), - "expected cookies extracted"); - - is(ref($result{foo}), 'CGI::Cookie', 'Type of objects returned is correct'); - is($result{foo}->value, 'a phrase', "cookie foo is correct"); - is($result{bar}->value, 'yes, a phrase', "cookie bar is correct"); - is($result{baz}->value, '^wibble', "cookie baz is correct"); - is($result{qux}->value, "'", "cookie qux is correct"); -} - -#----------------------------------------------------------------------------- -# Test raw_fetch -#----------------------------------------------------------------------------- - -{ - # make sure there are no cookies in the environment - delete $ENV{HTTP_COOKIE}; - delete $ENV{COOKIE}; - - my %result = CGI::Cookie->raw_fetch(); - ok(keys %result == 0, "No cookies in environment, returns empty list"); - - # now set a cookie in the environment and try again - $ENV{HTTP_COOKIE} = $test_cookie[2]; - %result = CGI::Cookie->raw_fetch(); - ok(eq_set([keys %result], [qw(foo bar baz qux)]), - "expected cookies extracted"); - - is(ref($result{foo}), '', 'Plain scalar returned'); - is($result{foo}, 'vixen', "cookie foo is correct"); - is($result{bar}, 'cow', "cookie bar is correct"); - is($result{baz}, 'bitch', "cookie baz is correct"); - is($result{qux}, 'politician', "cookie qux is correct"); - - # Delete that and make sure it goes away - delete $ENV{HTTP_COOKIE}; - %result = CGI::Cookie->raw_fetch(); - ok(keys %result == 0, "No cookies in environment, returns empty list"); - - # try another cookie in the other environment variable thats supposed to work - $ENV{COOKIE} = $test_cookie[3]; - %result = CGI::Cookie->raw_fetch(); - ok(eq_set([keys %result], [qw(foo bar baz qux)]), - "expected cookies extracted"); - - is(ref($result{foo}), '', 'Plain scalar returned'); - is($result{foo}, 'a%20phrase', "cookie foo is correct"); - is($result{bar}, 'yes%2C%20a%20phrase', "cookie bar is correct"); - is($result{baz}, '%5Ewibble', "cookie baz is correct"); - is($result{qux}, '%27', "cookie qux is correct"); -} - -#----------------------------------------------------------------------------- -# Test new -#----------------------------------------------------------------------------- - -{ - # Try new with full information provided - my $c = CGI::Cookie->new(-name => 'foo', - -value => 'bar', - -expires => '+3M', - -domain => '.capricorn.com', - -path => '/cgi-bin/database', - -secure => 1 - ); - is(ref($c), 'CGI::Cookie', 'new returns objects of correct type'); - is($c->name , 'foo', 'name is correct'); - is($c->value , 'bar', 'value is correct'); - like($c->expires, '/^[a-z]{3},\s*\d{2}-[a-z]{3}-\d{4}/i', 'expires in correct format'); - is($c->domain , '.capricorn.com', 'domain is correct'); - is($c->path , '/cgi-bin/database', 'path is correct'); - ok($c->secure , 'secure attribute is set'); - - # now try it with the only two manditory values (should also set the default path) - $c = CGI::Cookie->new(-name => 'baz', - -value => 'qux', - ); - is(ref($c), 'CGI::Cookie', 'new returns objects of correct type'); - is($c->name , 'baz', 'name is correct'); - is($c->value , 'qux', 'value is correct'); - ok(!defined $c->expires, 'expires is not set'); - ok(!defined $c->domain , 'domain attributeis not set'); - is($c->path, '/', 'path atribute is set to default'); - ok(!defined $c->secure , 'secure attribute is set'); - -# I'm really not happy about the restults of this section. You pass -# the new method invalid arguments and it just merilly creates a -# broken object :-) -# I've commented them out because they currently pass but I don't -# think they should. I think this is testing broken behaviour :-( - -# # This shouldn't work -# $c = CGI::Cookie->new(-name => 'baz' ); -# -# is(ref($c), 'CGI::Cookie', 'new returns objects of correct type'); -# is($c->name , 'baz', 'name is correct'); -# ok(!defined $c->value, "Value is undefined "); -# ok(!defined $c->expires, 'expires is not set'); -# ok(!defined $c->domain , 'domain attributeis not set'); -# is($c->path , '/', 'path atribute is set to default'); -# ok(!defined $c->secure , 'secure attribute is set'); - -} - -#----------------------------------------------------------------------------- -# Test as_string -#----------------------------------------------------------------------------- - -{ - my $c = CGI::Cookie->new(-name => 'Jam', - -value => 'Hamster', - -expires => '+3M', - -domain => '.pie-shop.com', - -path => '/', - -secure => 1 - ); - - my $name = $c->name; - like($c->as_string, "/$name/", "Stringified cookie contains name"); - - my $value = $c->value; - like($c->as_string, "/$value/", "Stringified cookie contains value"); - - my $expires = $c->expires; - like($c->as_string, "/$expires/", "Stringified cookie contains expires"); - - my $domain = $c->domain; - like($c->as_string, "/$domain/", "Stringified cookie contains domain"); - - my $path = $c->path; - like($c->as_string, "/$path/", "Stringified cookie contains path"); - - like($c->as_string, '/secure/', "Stringified cookie contains secure"); - - $c = CGI::Cookie->new(-name => 'Hamster-Jam', - -value => 'Tulip', - ); - - $name = $c->name; - like($c->as_string, "/$name/", "Stringified cookie contains name"); - - $value = $c->value; - like($c->as_string, "/$value/", "Stringified cookie contains value"); - - ok($c->as_string !~ /expires/, "Stringified cookie has no expires field"); - - ok($c->as_string !~ /domain/, "Stringified cookie has no domain field"); - - $path = $c->path; - like($c->as_string, "/$path/", "Stringified cookie contains path"); - - ok($c->as_string !~ /secure/, "Stringified cookie does not contain secure"); -} - -#----------------------------------------------------------------------------- -# Test compare -#----------------------------------------------------------------------------- - -{ - my $c1 = CGI::Cookie->new(-name => 'Jam', - -value => 'Hamster', - -expires => '+3M', - -domain => '.pie-shop.com', - -path => '/', - -secure => 1 - ); - - # have to use $c1->expires because the time will occasionally be - # different between the two creates causing spurious failures. - my $c2 = CGI::Cookie->new(-name => 'Jam', - -value => 'Hamster', - -expires => $c1->expires, - -domain => '.pie-shop.com', - -path => '/', - -secure => 1 - ); - - # This looks titally whacked, but it does the -1, 0, 1 comparison - # thing so 0 means they match - is($c1->compare("$c1"), 0, "Cookies are identical"); - is($c1->compare("$c2"), 0, "Cookies are identical"); - - $c1 = CGI::Cookie->new(-name => 'Jam', - -value => 'Hamster', - -domain => '.foo.bar.com' - ); - - # have to use $c1->expires because the time will occasionally be - # different between the two creates causing spurious failures. - $c2 = CGI::Cookie->new(-name => 'Jam', - -value => 'Hamster', - ); - - # This looks titally whacked, but it does the -1, 0, 1 comparison - # thing so 0 (i.e. false) means they match - is($c1->compare("$c1"), 0, "Cookies are identical"); - ok($c1->compare("$c2"), "Cookies are not identical"); - - $c2->domain('.foo.bar.com'); - is($c1->compare("$c2"), 0, "Cookies are identical"); -} - -#----------------------------------------------------------------------------- -# Test name, value, domain, secure, expires and path -#----------------------------------------------------------------------------- - -{ - my $c = CGI::Cookie->new(-name => 'Jam', - -value => 'Hamster', - -expires => '+3M', - -domain => '.pie-shop.com', - -path => '/', - -secure => 1 - ); - - is($c->name, 'Jam', 'name is correct'); - is($c->name('Clash'), 'Clash', 'name is set correctly'); - is($c->name, 'Clash', 'name now returns updated value'); - - # this is insane! it returns a simple scalar but can't accept one as - # an argument, you have to give it an arrary ref. It's totally - # inconsitent with these other methods :-( - is($c->value, 'Hamster', 'value is correct'); - is($c->value(['Gerbil']), 'Gerbil', 'value is set correctly'); - is($c->value, 'Gerbil', 'value now returns updated value'); - - my $exp = $c->expires; - like($c->expires, '/^[a-z]{3},\s*\d{2}-[a-z]{3}-\d{4}/i', 'expires is correct'); - like($c->expires('+12h'), '/^[a-z]{3},\s*\d{2}-[a-z]{3}-\d{4}/i', 'expires is set correctly'); - like($c->expires, '/^[a-z]{3},\s*\d{2}-[a-z]{3}-\d{4}/i', 'expires now returns updated value'); - isnt($c->expires, $exp, "Expiry time has changed"); - - is($c->domain, '.pie-shop.com', 'domain is correct'); - is($c->domain('.wibble.co.uk'), '.wibble.co.uk', 'domain is set correctly'); - is($c->domain, '.wibble.co.uk', 'domain now returns updated value'); - - is($c->path, '/', 'path is correct'); - is($c->path('/basket/'), '/basket/', 'path is set correctly'); - is($c->path, '/basket/', 'path now returns updated value'); - - ok($c->secure, 'secure attribute is set'); - ok(!$c->secure(0), 'secure attribute is cleared'); - ok(!$c->secure, 'secure attribute is cleared'); -} - -#----------------------------------------------------------------------------- -# Apache2?::Cookie compatibility. -#----------------------------------------------------------------------------- -APACHEREQ: { - my $r = Apache::Faker->new; - isa_ok $r, 'Apache'; - ok my $c = CGI::Cookie->new( - $r, - -name => 'Foo', - -value => 'Bar', - ), 'Pass an Apache object to the CGI::Cookie constructor'; - isa_ok $c, 'CGI::Cookie'; - ok $c->bake($r), 'Bake the cookie'; - ok eq_array( $r->{check}, [ 'Set-Cookie', $c->as_string ]), - 'bake() should call headers_out->set()'; - - $r = Apache2::Faker->new; - isa_ok $r, 'Apache2::RequestReq'; - ok $c = CGI::Cookie->new( - $r, - -name => 'Foo', - -value => 'Bar', - ), 'Pass an Apache::RequestReq object to the CGI::Cookie constructor'; - isa_ok $c, 'CGI::Cookie'; - ok $c->bake($r), 'Bake the cookie'; - ok eq_array( $r->{check}, [ 'Set-Cookie', $c->as_string ]), - 'bake() should call headers_out->set()'; -} - - -package Apache::Faker; -sub new { bless {}, shift } -sub isa { - my ($self, $pkg) = @_; - return $pkg eq 'Apache'; -} -sub headers_out { shift } -sub add { shift->{check} = \@_; } - -package Apache2::Faker; -sub new { bless {}, shift } -sub isa { - my ($self, $pkg) = @_; - return $pkg eq 'Apache2::RequestReq'; -} -sub headers_out { shift } -sub add { shift->{check} = \@_; } diff --git a/ext/CGI/t/fast.t b/ext/CGI/t/fast.t deleted file mode 100644 index 45f8e1271c..0000000000 --- a/ext/CGI/t/fast.t +++ /dev/null @@ -1,37 +0,0 @@ -#!./perl -w - -use lib qw(t/lib); - -# Due to a bug in older versions of MakeMaker & Test::Harness, we must -# ensure the blib's are in @INC, else we might use the core CGI.pm -use lib qw(blib/lib blib/arch); - -my $fcgi; -BEGIN { - local $@; - eval { require FCGI }; - $fcgi = $@ ? 0 : 1; -} - -use Test::More tests => 7; - -# Shut up "used only once" warnings. -() = $CGI::Q; -() = $CGI::Fast::Ext_Request; - -SKIP: { - skip( 'FCGI not installed, cannot continue', 7 ) unless $fcgi; - - use_ok( CGI::Fast ); - ok( my $q = CGI::Fast->new(), 'created new CGI::Fast object' ); - is( $q, $CGI::Q, 'checking to see if the object was stored properly' ); - is( $q->param(), (), 'no params' ); - - ok( $q = CGI::Fast->new({ foo => 'bar' }), 'creating obect with params' ); - is( $q->param('foo'), 'bar', 'checking passed param' ); - - # if this is false, the package var will be empty - $ENV{FCGI_SOCKET_PATH} = 0; - is( $CGI::Fast::Ext_Request, '', 'checking no active request' ); - -} diff --git a/ext/CGI/t/form.t b/ext/CGI/t/form.t deleted file mode 100644 index b532db9841..0000000000 --- a/ext/CGI/t/form.t +++ /dev/null @@ -1,177 +0,0 @@ -#!/usr/local/bin/perl -w - -use Test::More tests => 22; - -BEGIN { use_ok('CGI'); }; -use CGI (':standard','-no_debug','-tabindex'); - -my $CRLF = "\015\012"; -if ($^O eq 'VMS') { - $CRLF = "\n"; # via web server carriage is inserted automatically -} -if (ord("\t") != 9) { # EBCDIC? - $CRLF = "\r\n"; -} - - -# Set up a CGI environment -$ENV{REQUEST_METHOD} = 'GET'; -$ENV{QUERY_STRING} = 'game=chess&game=checkers&weather=dull'; -$ENV{PATH_INFO} = '/somewhere/else'; -$ENV{PATH_TRANSLATED} = '/usr/local/somewhere/else'; -$ENV{SCRIPT_NAME} ='/cgi-bin/foo.cgi'; -$ENV{SERVER_PROTOCOL} = 'HTTP/1.0'; -$ENV{SERVER_PORT} = 8080; -$ENV{SERVER_NAME} = 'the.good.ship.lollypop.com'; - -is(start_form(-action=>'foobar',-method=>'get'), - qq(<form method="get" action="foobar" enctype="multipart/form-data">\n), - "start_form()"); - -is(submit(), - qq(<input type="submit" tabindex="1" name=".submit" />), - "submit()"); - -is(submit(-name => 'foo', - -value => 'bar'), - qq(<input type="submit" tabindex="2" name="foo" value="bar" />), - "submit(-name,-value)"); - -is(submit({-name => 'foo', - -value => 'bar'}), - qq(<input type="submit" tabindex="3" name="foo" value="bar" />), - "submit({-name,-value})"); - -is(textfield(-name => 'weather'), - qq(<input type="text" name="weather" tabindex="4" value="dull" />), - "textfield({-name})"); - -is(textfield(-name => 'weather', - -value => 'nice'), - qq(<input type="text" name="weather" tabindex="5" value="dull" />), - "textfield({-name,-value})"); - -is(textfield(-name => 'weather', - -value => 'nice', - -override => 1), - qq(<input type="text" name="weather" tabindex="6" value="nice" />), - "textfield({-name,-value,-override})"); - -is(checkbox(-name => 'weather', - -value => 'nice'), - qq(<label><input type="checkbox" name="weather" value="nice" tabindex="7" />weather</label>), - "checkbox()"); - -is(checkbox(-name => 'weather', - -value => 'nice', - -label => 'forecast'), - qq(<label><input type="checkbox" name="weather" value="nice" tabindex="8" />forecast</label>), - "checkbox()"); - -is(checkbox(-name => 'weather', - -value => 'nice', - -label => 'forecast', - -checked => 1, - -override => 1), - qq(<label><input type="checkbox" name="weather" value="nice" tabindex="9" checked="checked" />forecast</label>), - "checkbox()"); - -is(checkbox(-name => 'weather', - -value => 'dull', - -label => 'forecast'), - qq(<label><input type="checkbox" name="weather" value="dull" tabindex="10" checked="checked" />forecast</label>), - "checkbox()"); - -is(radio_group(-name => 'game'), - qq(<label><input type="radio" name="game" value="chess" checked="checked" tabindex="11" />chess</label> <label><input type="radio" name="game" value="checkers" tabindex="12" />checkers</label>), - 'radio_group()'); - -is(radio_group(-name => 'game', - -labels => {'chess' => 'ping pong'}), - qq(<label><input type="radio" name="game" value="chess" checked="checked" tabindex="13" />ping pong</label> <label><input type="radio" name="game" value="checkers" tabindex="14" />checkers</label>), - 'radio_group()'); - -is(checkbox_group(-name => 'game', - -Values => [qw/checkers chess cribbage/]), - qq(<label><input type="checkbox" name="game" value="checkers" checked="checked" tabindex="15" />checkers</label> <label><input type="checkbox" name="game" value="chess" checked="checked" tabindex="16" />chess</label> <label><input type="checkbox" name="game" value="cribbage" tabindex="17" />cribbage</label>), - 'checkbox_group()'); - -is(checkbox_group(-name => 'game', - '-values' => [qw/checkers chess cribbage/], - '-defaults' => ['cribbage'], - -override=>1), - qq(<label><input type="checkbox" name="game" value="checkers" tabindex="18" />checkers</label> <label><input type="checkbox" name="game" value="chess" tabindex="19" />chess</label> <label><input type="checkbox" name="game" value="cribbage" checked="checked" tabindex="20" />cribbage</label>), - 'checkbox_group()'); - -is(popup_menu(-name => 'game', - '-values' => [qw/checkers chess cribbage/], - -default => 'cribbage', - -override => 1), - '<select name="game" tabindex="21" > -<option value="checkers">checkers</option> -<option value="chess">chess</option> -<option selected="selected" value="cribbage">cribbage</option> -</select>', - 'popup_menu()'); -is(scrolling_list(-name => 'game', - '-values' => [qw/checkers chess cribbage/], - -default => 'cribbage', - -override=>1), - '<select name="game" tabindex="22" size="3"> -<option value="checkers">checkers</option> -<option value="chess">chess</option> -<option selected="selected" value="cribbage">cribbage</option> -</select>', - 'scrolling_list()'); - -is(checkbox_group(-name => 'game', - -Values => [qw/checkers chess cribbage/], - -disabled => ['checkers']), - qq(<label><input type="checkbox" name="game" value="checkers" checked="checked" tabindex="23" disabled='1'/><span style="color:gray">checkers</span></label> <label><input type="checkbox" name="game" value="chess" checked="checked" tabindex="24" />chess</label> <label><input type="checkbox" name="game" value="cribbage" tabindex="25" />cribbage</label>), - 'checkbox_group()'); - -my $optgroup = optgroup(-name=>'optgroup_name', - -Values => ['moe','catch'], - -attributes=>{'catch'=>{'class'=>'red'}}); - -is($optgroup, - qq(<optgroup label="optgroup_name"> -<option value="moe">moe</option> -<option class="red" value="catch">catch</option> -</optgroup>), - 'optgroup()'); - -is(popup_menu(-name=>'menu_name', - -Values=>[qw/eenie meenie minie/, $optgroup], - -labels=>{'eenie'=>'one', - 'meenie'=>'two', - 'minie'=>'three'}, - -default=>'meenie'), - qq(<select name="menu_name" tabindex="26" > -<option value="eenie">one</option> -<option selected="selected" value="meenie">two</option> -<option value="minie">three</option> -<optgroup label="optgroup_name"> -<option value="moe">moe</option> -<option class="red" value="catch">catch</option> -</optgroup> -</select>), - 'popup_menu() + optgroup()'); - -is(scrolling_list(-name=>'menu_name', - -Values=>[qw/eenie meenie minie/, $optgroup], - -labels=>{'eenie'=>'one', - 'meenie'=>'two', - 'minie'=>'three'}, - -default=>'meenie'), - qq(<select name="menu_name" tabindex="27" size="4"> -<option value="eenie">one</option> -<option selected="selected" value="meenie">two</option> -<option value="minie">three</option> -<optgroup label="optgroup_name"> -<option value="moe">moe</option> -<option class="red" value="catch">catch</option> -</optgroup> -</select>), - 'scrolling_list() + optgroup()'); - diff --git a/ext/CGI/t/function.t b/ext/CGI/t/function.t deleted file mode 100644 index 4ff67d581b..0000000000 --- a/ext/CGI/t/function.t +++ /dev/null @@ -1,117 +0,0 @@ -#!/usr/local/bin/perl -w - -use lib qw(t/lib); - -# Test ability to retrieve HTTP request info -######################### We start with some black magic to print on failure. -use lib '.','..','../blib/lib','../blib/arch'; - -BEGIN {$| = 1; print "1..32\n"; } -END {print "not ok 1\n" unless $loaded;} -use Config; -use CGI (':standard','keywords'); -$loaded = 1; -print "ok 1\n"; - -######################### End of black magic. - -# util -sub test { - local($^W) = 0; - my($num, $true,$msg) = @_; - print($true ? "ok $num\n" : "not ok $num $msg\n"); -} - -my $CRLF = "\015\012"; - -# A peculiarity of sending "\n" through MBX|Socket|web-server on VMS -# is that a CR character gets inserted automatically in the web server -# case but not internal to perl's double quoted strings "\n". This -# test would need to be modified to use the "\015\012" on VMS if it -# were actually run through a web server. -# Thanks to Peter Prymmer for this - -if ($^O eq 'VMS') { $CRLF = "\n"; } - -# Web servers on EBCDIC hosts are typically set up to do an EBCDIC -> ASCII -# translation hence CRLF is used as \r\n within CGI.pm on such machines. - -if (ord("\t") != 9) { $CRLF = "\r\n"; } - -# Web servers on EBCDIC hosts are typically set up to do an EBCDIC -> ASCII -# translation hence CRLF is used as \r\n within CGI.pm on such machines. - -if (ord("\t") != 9) { $CRLF = "\r\n"; } - -# Set up a CGI environment -$ENV{REQUEST_METHOD}='GET'; -$ENV{QUERY_STRING} ='game=chess&game=checkers&weather=dull'; -$ENV{PATH_INFO} ='/somewhere/else'; -$ENV{PATH_TRANSLATED} ='/usr/local/somewhere/else'; -$ENV{SCRIPT_NAME} ='/cgi-bin/foo.cgi'; -$ENV{SERVER_PROTOCOL} = 'HTTP/1.0'; -$ENV{SERVER_PORT} = 8080; -$ENV{SERVER_NAME} = 'the.good.ship.lollypop.com'; -$ENV{HTTP_LOVE} = 'true'; - -test(2,request_method() eq 'GET',"CGI::request_method()"); -test(3,query_string() eq 'game=chess;game=checkers;weather=dull',"CGI::query_string()"); -test(4,param() == 2,"CGI::param()"); -test(5,join(' ',sort {$a cmp $b} param()) eq 'game weather',"CGI::param()"); -test(6,param('game') eq 'chess',"CGI::param()"); -test(7,param('weather') eq 'dull',"CGI::param()"); -test(8,join(' ',param('game')) eq 'chess checkers',"CGI::param()"); -test(9,param(-name=>'foo',-value=>'bar'),'CGI::param() put'); -test(10,param(-name=>'foo') eq 'bar','CGI::param() get'); -test(11,query_string() eq 'game=chess;game=checkers;weather=dull;foo=bar',"CGI::query_string() redux"); -test(12,http('love') eq 'true',"CGI::http()"); -test(13,script_name() eq '/cgi-bin/foo.cgi',"CGI::script_name()"); -test(14,url() eq 'http://the.good.ship.lollypop.com:8080/cgi-bin/foo.cgi',"CGI::url()"); -test(15,self_url() eq - 'http://the.good.ship.lollypop.com:8080/cgi-bin/foo.cgi/somewhere/else?game=chess;game=checkers;weather=dull;foo=bar', - "CGI::url()"); -test(16,url(-absolute=>1) eq '/cgi-bin/foo.cgi','CGI::url(-absolute=>1)'); -test(17,url(-relative=>1) eq 'foo.cgi','CGI::url(-relative=>1)'); -test(18,url(-relative=>1,-path=>1) eq 'foo.cgi/somewhere/else','CGI::url(-relative=>1,-path=>1)'); -test(19,url(-relative=>1,-path=>1,-query=>1) eq - 'foo.cgi/somewhere/else?game=chess;game=checkers;weather=dull;foo=bar', - 'CGI::url(-relative=>1,-path=>1,-query=>1)'); -Delete('foo'); -test(20,!param('foo'),'CGI::delete()'); - -CGI::_reset_globals(); -$ENV{QUERY_STRING}='mary+had+a+little+lamb'; -test(21,join(' ',keywords()) eq 'mary had a little lamb','CGI::keywords'); -test(22,join(' ',param('keywords')) eq 'mary had a little lamb','CGI::keywords'); - -CGI::_reset_globals; -if ($Config{d_fork}) { - $test_string = 'game=soccer&game=baseball&weather=nice'; - $ENV{REQUEST_METHOD}='POST'; - $ENV{CONTENT_LENGTH}=length($test_string); - $ENV{QUERY_STRING}='big_balls=basketball&small_balls=golf'; - if (open(CHILD,"|-")) { # cparent - print CHILD $test_string; - close CHILD; - exit 0; - } - # at this point, we're in a new (child) process - test(23,param('weather') eq 'nice',"CGI::param() from POST"); - test(24,(url_param('big_balls') eq 'basketball'),"CGI::url_param()"); -} else { - print "ok 23 # Skip\n"; - print "ok 24 # Skip\n"; -} -test(25,redirect('http://somewhere.else') eq "Status: 302 Found${CRLF}Location: http://somewhere.else${CRLF}${CRLF}","CGI::redirect() 1"); -my $h = redirect(-Location=>'http://somewhere.else',-Type=>'text/html'); -test(26,$h eq "Status: 302 Found${CRLF}Location: http://somewhere.else${CRLF}Content-Type: text/html; charset=ISO-8859-1${CRLF}${CRLF}","CGI::redirect() 2"); -test(27,redirect(-Location=>'http://somewhere.else/bin/foo&bar',-Type=>'text/html') eq "Status: 302 Found${CRLF}Location: http://somewhere.else/bin/foo&bar${CRLF}Content-Type: text/html; charset=ISO-8859-1${CRLF}${CRLF}","CGI::redirect() 2"); - -test(28,escapeHTML('CGI') eq 'CGI','escapeHTML(CGI) failing again'); - -test(29, charset("UTF-8") && header() eq "Content-Type: text/html; charset=UTF-8${CRLF}${CRLF}", "UTF-8 charset"); -test(30, !charset("") && header() eq "Content-Type: text/html${CRLF}${CRLF}", "Empty charset"); - -test(31, header(-foo=>'bar') eq "Foo: bar${CRLF}Content-Type: text/html${CRLF}${CRLF}", "Custom header"); - -test(32, start_form(-action=>'one',name=>'two',onsubmit=>'three') eq qq(<form method="post" action="one" enctype="multipart/form-data" onsubmit="three" name="two">\n), "initial dash followed by undashed arguments"); diff --git a/ext/CGI/t/html.t b/ext/CGI/t/html.t deleted file mode 100644 index 49cc595950..0000000000 --- a/ext/CGI/t/html.t +++ /dev/null @@ -1,113 +0,0 @@ -#!/usr/local/bin/perl -w - -# Test ability to retrieve HTTP request info -######################### We start with some black magic to print on failure. -use lib '../blib/lib','../blib/arch'; - -END {print "not ok 1\n" unless $loaded;} -use CGI (':standard','-no_debug','*h3','start_table'); -$loaded = 1; -print "ok 1\n"; - -BEGIN { - $| = 1; print "1..28\n"; - if( $] > 5.006 ) { - # no utf8 - require utf8; # we contain Latin-1 - utf8->unimport; - } -} - -######################### End of black magic. - -my $CRLF = "\015\012"; -if ($^O eq 'VMS') { - $CRLF = "\n"; # via web server carriage is inserted automatically -} -if (ord("\t") != 9) { # EBCDIC? - $CRLF = "\r\n"; -} - - -# util -sub test { - local($^W) = 0; - my($num, $true,$msg) = @_; - print($true ? "ok $num\n" : "not ok $num $msg\n"); -} - -# all the automatic tags -test(2,h1() eq '<h1 />',"single tag"); -test(3,h1('fred') eq '<h1>fred</h1>',"open/close tag"); -test(4,h1('fred','agnes','maura') eq '<h1>fred agnes maura</h1>',"open/close tag multiple"); -test(5,h1({-align=>'CENTER'},'fred') eq '<h1 align="CENTER">fred</h1>',"open/close tag with attribute"); -test(6,h1({-align=>undef},'fred') eq '<h1 align>fred</h1>',"open/close tag with orphan attribute"); -test(7,h1({-align=>'CENTER'},['fred','agnes']) eq - '<h1 align="CENTER">fred</h1> <h1 align="CENTER">agnes</h1>', - "distributive tag with attribute"); -{ - local($") = '-'; - test(8,h1('fred','agnes','maura') eq '<h1>fred-agnes-maura</h1>',"open/close tag \$\" interpolation"); -} -test(9,header() eq "Content-Type: text/html; charset=ISO-8859-1${CRLF}${CRLF}","header()"); -test(10,header(-type=>'image/gif') eq "Content-Type: image/gif${CRLF}${CRLF}","header()"); -test(11,header(-type=>'image/gif',-status=>'500 Sucks') eq "Status: 500 Sucks${CRLF}Content-Type: image/gif${CRLF}${CRLF}","header()"); -test(12,header(-nph=>1) =~ m!HTTP/1.0 200 OK${CRLF}Server: cmdline${CRLF}Date:.+${CRLF}Content-Type: text/html; charset=ISO-8859-1${CRLF}${CRLF}!,"header()"); -test(13,start_html() eq <<END,"start_html()"); -<!DOCTYPE html - PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US"> -<head> -<title>Untitled Document</title> -<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> -</head> -<body> -END - ; -test(14,start_html(-Title=>'The world of foo') eq <<END,"start_html()"); -<!DOCTYPE html - PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US"> -<head> -<title>The world of foo</title> -<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> -</head> -<body> -END - ; -# Note that this test will turn off XHTML until we make a new CGI object. -test(15,start_html(-dtd=>"-//IETF//DTD HTML 3.2//FR",-lang=>'fr') eq <<END,"start_html()"); -<!DOCTYPE html - PUBLIC "-//IETF//DTD HTML 3.2//FR"> -<html lang="fr"><head><title>Untitled Document</title> -</head> -<body> -END - ; -test(16,($cookie=cookie(-name=>'fred',-value=>['chocolate','chip'],-path=>'/')) eq 'fred=chocolate&chip; path=/',"cookie()"); -my $h = header(-Cookie=>$cookie); -test(17,$h =~ m!^Set-Cookie: fred=chocolate&chip\; path=/${CRLF}Date:.*${CRLF}Content-Type: text/html; charset=ISO-8859-1${CRLF}${CRLF}!s, - "header(-cookie)"); -test(18,start_h3 eq '<h3>'); -test(19,end_h3 eq '</h3>'); -test(20,start_table({-border=>undef}) eq '<table border>'); -test(21,h1(escapeHTML("this is <not> \x8bright\x9b")) eq '<h1>this is <not> ‹right›</h1>'); -charset('utf-8'); -if (ord("\t") == 9) { -test(22,h1(escapeHTML("this is <not> \x8bright\x9b")) eq '<h1>this is <not> ‹right›</h1>'); -} -else { -test(22,h1(escapeHTML("this is <not> \x8bright\x9b")) eq '<h1>this is <not> »rightº</h1>'); -} -test(23,i(p('hello there')) eq '<i><p>hello there</p></i>'); -my $q = new CGI; -test(24,$q->h1('hi') eq '<h1>hi</h1>'); - -$q->autoEscape(1); -test(25,$q->p({title=>"hello worldè"},'hello á') eq '<p title="hello world&egrave;">hello á</p>'); -$q->autoEscape(0); -test(26,$q->p({title=>"hello worldè"},'hello á') eq '<p title="hello worldè">hello á</p>'); -test(27,p({title=>"hello worldè"},'hello á') eq '<p title="hello world&egrave;">hello á</p>'); -test(28,header(-type=>'image/gif',-charset=>'UTF-8') eq "Content-Type: image/gif; charset=UTF-8${CRLF}${CRLF}","header()"); diff --git a/ext/CGI/t/no_tabindex.t b/ext/CGI/t/no_tabindex.t deleted file mode 100644 index c9a7fb8fb6..0000000000 --- a/ext/CGI/t/no_tabindex.t +++ /dev/null @@ -1,126 +0,0 @@ -#!/usr/local/bin/perl -w - -# Due to a bug in older versions of MakeMaker & Test::Harness, we must -# ensure the blib's are in @INC, else we might use the core CGI.pm -use lib qw(. ./blib/lib ./blib/arch); - -use Test::More tests => 18; - -BEGIN { use_ok('CGI'); }; -use CGI (':standard','-no_debug'); - -my $CRLF = "\015\012"; -if ($^O eq 'VMS') { - $CRLF = "\n"; # via web server carriage is inserted automatically -} -if (ord("\t") != 9) { # EBCDIC? - $CRLF = "\r\n"; -} - - -# Set up a CGI environment -$ENV{REQUEST_METHOD} = 'GET'; -$ENV{QUERY_STRING} = 'game=chess&game=checkers&weather=dull'; -$ENV{PATH_INFO} = '/somewhere/else'; -$ENV{PATH_TRANSLATED} = '/usr/local/somewhere/else'; -$ENV{SCRIPT_NAME} ='/cgi-bin/foo.cgi'; -$ENV{SERVER_PROTOCOL} = 'HTTP/1.0'; -$ENV{SERVER_PORT} = 8080; -$ENV{SERVER_NAME} = 'the.good.ship.lollypop.com'; - -ok( (not $CGI::TABINDEX), "Tab index turned off."); - -is(submit(), - qq(<input type="submit" name=".submit" />), - "submit()"); - -is(submit(-name => 'foo', - -value => 'bar'), - qq(<input type="submit" name="foo" value="bar" />), - "submit(-name,-value)"); - -is(submit({-name => 'foo', - -value => 'bar'}), - qq(<input type="submit" name="foo" value="bar" />), - "submit({-name,-value})"); - -is(textfield(-name => 'weather'), - qq(<input type="text" name="weather" value="dull" />), - "textfield({-name})"); - -is(textfield(-name => 'weather', - -value => 'nice'), - qq(<input type="text" name="weather" value="dull" />), - "textfield({-name,-value})"); - -is(textfield(-name => 'weather', - -value => 'nice', - -override => 1), - qq(<input type="text" name="weather" value="nice" />), - "textfield({-name,-value,-override})"); - -is(checkbox(-name => 'weather', - -value => 'nice'), - qq(<label><input type="checkbox" name="weather" value="nice" />weather</label>), - "checkbox()"); - -is(checkbox(-name => 'weather', - -value => 'nice', - -label => 'forecast'), - qq(<label><input type="checkbox" name="weather" value="nice" />forecast</label>), - "checkbox()"); - -is(checkbox(-name => 'weather', - -value => 'nice', - -label => 'forecast', - -checked => 1, - -override => 1), - qq(<label><input type="checkbox" name="weather" value="nice" checked="checked" />forecast</label>), - "checkbox()"); - -is(checkbox(-name => 'weather', - -value => 'dull', - -label => 'forecast'), - qq(<label><input type="checkbox" name="weather" value="dull" checked="checked" />forecast</label>), - "checkbox()"); - -is(radio_group(-name => 'game'), - qq(<label><input type="radio" name="game" value="chess" checked="checked" />chess</label> <label><input type="radio" name="game" value="checkers" />checkers</label>), - 'radio_group()'); - -is(radio_group(-name => 'game', - -labels => {'chess' => 'ping pong'}), - qq(<label><input type="radio" name="game" value="chess" checked="checked" />ping pong</label> <label><input type="radio" name="game" value="checkers" />checkers</label>), - 'radio_group()'); - -is(checkbox_group(-name => 'game', - -Values => [qw/checkers chess cribbage/]), - qq(<label><input type="checkbox" name="game" value="checkers" checked="checked" />checkers</label> <label><input type="checkbox" name="game" value="chess" checked="checked" />chess</label> <label><input type="checkbox" name="game" value="cribbage" />cribbage</label>), - 'checkbox_group()'); - -is(checkbox_group(-name => 'game', - '-values' => [qw/checkers chess cribbage/], - '-defaults' => ['cribbage'], - -override=>1), - qq(<label><input type="checkbox" name="game" value="checkers" />checkers</label> <label><input type="checkbox" name="game" value="chess" />chess</label> <label><input type="checkbox" name="game" value="cribbage" checked="checked" />cribbage</label>), - 'checkbox_group()'); - -is(popup_menu(-name => 'game', - '-values' => [qw/checkers chess cribbage/], - -default => 'cribbage', - -override => 1), - '<select name="game" > -<option value="checkers">checkers</option> -<option value="chess">chess</option> -<option selected="selected" value="cribbage">cribbage</option> -</select>', - 'popup_menu()'); - - -is(textarea(-name=>'foo', - -default=>'starting value', - -rows=>10, - -columns=>50), - '<textarea name="foo" rows="10" cols="50">starting value</textarea>', - 'textarea()'); - diff --git a/ext/CGI/t/popup_menu.t b/ext/CGI/t/popup_menu.t deleted file mode 100644 index 3c7d33ee62..0000000000 --- a/ext/CGI/t/popup_menu.t +++ /dev/null @@ -1,15 +0,0 @@ -#!perl -# Tests for popup_menu(); -use lib 't/lib'; -use Test::More 'no_plan'; -use CGI; - -my $q = CGI->new; - -is ( $q->popup_menu(-name=>"foo", - values=>[0,1], -default=>0), -'<select name="foo" > -<option selected="selected" value="0">0</option> -<option value="1">1</option> -</select>' -, 'popup_menu(): basic test, including 0 as a default value'); - diff --git a/ext/CGI/t/pretty.t b/ext/CGI/t/pretty.t deleted file mode 100644 index d3c19c0c98..0000000000 --- a/ext/CGI/t/pretty.t +++ /dev/null @@ -1,121 +0,0 @@ -#!/bin/perl -w - -use strict; -use lib '.', 't/lib','../blib/lib','./blib/lib'; -use Test::More tests => 18; - -BEGIN { use_ok('CGI::Pretty') }; - -# This is silly use_ok should take arguments -use CGI::Pretty (':all'); - -is(h1(), '<h1 /> -',"single tag"); - -is(ol(li('fred'),li('ethel')), <<HTML, "basic indentation"); -<ol> - <li> - fred - </li> - <li> - ethel - </li> -</ol> -HTML - - -is(p('hi',pre('there'),'frog'), <<HTML, "<pre> tags"); -<p> - hi <pre>there</pre> - frog -</p> -HTML - -is(h1({-align=>'CENTER'},'fred'), <<HTML, "open/close tag with attribute"); -<h1 align="CENTER"> - fred -</h1> -HTML - -is(h1({-align=>undef},'fred'), <<HTML,"open/close tag with orphan attribute"); -<h1 align> - fred -</h1> -HTML - -is(h1({-align=>'CENTER'},['fred','agnes']), <<HTML, "distributive tag with attribute"); -<h1 align="CENTER"> - fred -</h1> -<h1 align="CENTER"> - agnes -</h1> -HTML - -is(p('hi',a({-href=>'frog'},'there'),'frog'), <<HTML, "as-is"); -<p> - hi <a href="frog">there</a> - frog -</p> -HTML - -is(p([ qw( hi there frog ) ] ), <<HTML, "array-reference"); -<p> - hi -</p> -<p> - there -</p> -<p> - frog -</p> -HTML - -is(p(p(p('hi'), 'there' ), 'frog'), <<HTML, "nested tags"); -<p> - <p> - <p> - hi - </p> - there - </p> - frog -</p> -HTML - -is(table(TR(td(table(TR(td('hi', 'there', 'frog')))))), <<HTML, "nested as-is tags"); -<table> - <tr> - <td><table> - <tr> - <td>hi there frog</td> - </tr> - </table></td> - </tr> -</table> -HTML - -is(table(TR(td(table(TR(td( [ qw( hi there frog ) ])))))), <<HTML, "nested as-is array-reference"); -<table> - <tr> - <td><table> - <tr> - <td>hi</td> - <td>there</td> - <td>frog</td> - </tr> - </table></td> - </tr> -</table> -HTML - -$CGI::Pretty::INDENT = $CGI::Pretty::LINEBREAK = ""; - -is(h1(), '<h1 />',"single tag (pretty turned off)"); -is(h1('fred'), '<h1>fred</h1>',"open/close tag (pretty turned off)"); -is(h1('fred','agnes','maura'), '<h1>fred agnes maura</h1>',"open/close tag multiple (pretty turned off)"); -is(h1({-align=>'CENTER'},'fred'), '<h1 align="CENTER">fred</h1>',"open/close tag with attribute (pretty turned off)"); -is(h1({-align=>undef},'fred'), '<h1 align>fred</h1>',"open/close tag with orphan attribute (pretty turned off)"); -is(h1({-align=>'CENTER'},['fred','agnes']), '<h1 align="CENTER">fred</h1> <h1 align="CENTER">agnes</h1>', - "distributive tag with attribute (pretty turned off)"); - diff --git a/ext/CGI/t/push.t b/ext/CGI/t/push.t deleted file mode 100644 index 2c48d60ba3..0000000000 --- a/ext/CGI/t/push.t +++ /dev/null @@ -1,85 +0,0 @@ -#!./perl -wT - -use lib qw(t/lib); - -# Due to a bug in older versions of MakeMaker & Test::Harness, we must -# ensure the blib's are in @INC, else we might use the core CGI.pm -use lib qw(blib/lib blib/arch); - -use Test::More tests => 12; - -use_ok( 'CGI::Push' ); - -ok( my $q = CGI::Push->new(), 'create a new CGI::Push object' ); - -# test the simple_counter() method -like( join('', $q->simple_counter(10)) , '/updated.+?10.+?times./', 'counter' ); - -# test do_sleep, except we don't want to bog down the tests -# there's also a potential timing-related failure lurking here -# change this variable at your own risk -my $sleep_in_tests = 0; - -SKIP: { - skip( 'do_sleep() test may take a while', 1 ) unless $sleep_in_tests; - - my $time = time; - CGI::Push::do_sleep(2); - is(time - $time, 2, 'slept for a while' ); -} - -# test push_delay() -ok( ! defined $q->push_delay(), 'no initial delay' ); -is( $q->push_delay(.5), .5, 'set a delay' ); - -my $out = tie *STDOUT, 'TieOut'; - -# next_page() to be called twice, last_page() once, no delay -my %vars = ( - -next_page => sub { return if $_[1] > 2; 'next page' }, - -last_page => sub { 'last page' }, - -delay => 0, -); - -$q->do_push(%vars); - -# this seems to appear on every page -like( $$out, '/WARNING: YOUR BROWSER/', 'unsupported browser warning' ); - -# these should appear correctly -is( ($$out =~ s/next page//g), 2, 'next_page callback called appropriately' ); -is( ($$out =~ s/last page//g), 1, 'last_page callback called appropriately' ); - -# send a fake content type (header capitalization varies in CGI, CGI::Push) -$$out = ''; -$q->do_push(%vars, -type => 'fake' ); -like( $$out, '/Content-[Tt]ype: fake/', 'set custom Content-type' ); - -# use our own counter, as $COUNTER in CGI::Push is now off -my $i; -$$out = ''; - -# no delay, custom headers from callback, only call callback once -$q->do_push( - -delay => 0, - -type => 'dynamic', - -next_page => sub { - return if $i++; - return $_[0]->header('text/plain'), 'arduk'; - }, -); - -# header capitalization again, our word should appear only once -like( $$out, '/ype: text\/plain/', 'set custom Content-type in next_page()' ); -is( $$out =~ s/arduk//g, 1, 'found text from next_page()' ); - -package TieOut; - -sub TIEHANDLE { - bless( \(my $text), $_[0] ); -} - -sub PRINT { - my $self = shift; - $$self .= join( $/, @_ ); -} diff --git a/ext/CGI/t/query_string.t b/ext/CGI/t/query_string.t deleted file mode 100644 index a792232683..0000000000 --- a/ext/CGI/t/query_string.t +++ /dev/null @@ -1,16 +0,0 @@ -#!perl - -# Tests for the query_string() method. - -use lib 't/lib'; -use Test::More 'no_plan'; -use CGI; - -{ - my $q1 = CGI->new('b=2;a=1;a=1'); - my $q2 = CGI->new('b=2&a=1&a=1'); - - is($q1->query_string - ,$q2->query_string - , "query string format is returned with the same delimiter regardless of input."); -} diff --git a/ext/CGI/t/request.t b/ext/CGI/t/request.t deleted file mode 100644 index 959986bc6c..0000000000 --- a/ext/CGI/t/request.t +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/local/bin/perl -w - -# Test ability to retrieve HTTP request info -######################### We start with some black magic to print on failure. -use lib '.','../blib/lib','../blib/arch'; - -BEGIN {$| = 1; print "1..34\n"; } -END {print "not ok 1\n" unless $loaded;} -use CGI (); -use Config; -$loaded = 1; -print "ok 1\n"; - -######################### End of black magic. - -# util -sub test { - local($^W) = 0; - my($num, $true,$msg) = @_; - print($true ? "ok $num\n" : "not ok $num $msg\n"); -} - -# Set up a CGI environment -$ENV{REQUEST_METHOD} = 'GET'; -$ENV{QUERY_STRING} = 'game=chess&game=checkers&weather=dull'; -$ENV{PATH_INFO} = '/somewhere/else'; -$ENV{PATH_TRANSLATED} = '/usr/local/somewhere/else'; -$ENV{SCRIPT_NAME} = '/cgi-bin/foo.cgi'; -$ENV{SERVER_PROTOCOL} = 'HTTP/1.0'; -$ENV{SERVER_PORT} = 8080; -$ENV{SERVER_NAME} = 'the.good.ship.lollypop.com'; -$ENV{REQUEST_URI} = "$ENV{SCRIPT_NAME}$ENV{PATH_INFO}?$ENV{QUERY_STRING}"; -$ENV{HTTP_LOVE} = 'true'; - -$q = new CGI; -test(2,$q,"CGI::new()"); -test(3,$q->request_method eq 'GET',"CGI::request_method()"); -test(4,$q->query_string eq 'game=chess;game=checkers;weather=dull',"CGI::query_string()"); -test(5,$q->param() == 2,"CGI::param()"); -test(6,join(' ',sort $q->param()) eq 'game weather',"CGI::param()"); -test(7,$q->param('game') eq 'chess',"CGI::param()"); -test(8,$q->param('weather') eq 'dull',"CGI::param()"); -test(9,join(' ',$q->param('game')) eq 'chess checkers',"CGI::param()"); -test(10,$q->param(-name=>'foo',-value=>'bar'),'CGI::param() put'); -test(11,$q->param(-name=>'foo') eq 'bar','CGI::param() get'); -test(12,$q->query_string eq 'game=chess;game=checkers;weather=dull;foo=bar',"CGI::query_string() redux"); -test(13,$q->http('love') eq 'true',"CGI::http()"); -test(14,$q->script_name eq '/cgi-bin/foo.cgi',"CGI::script_name()"); -test(15,$q->url eq 'http://the.good.ship.lollypop.com:8080/cgi-bin/foo.cgi',"CGI::url()"); -test(16,$q->self_url eq - 'http://the.good.ship.lollypop.com:8080/cgi-bin/foo.cgi/somewhere/else?game=chess;game=checkers;weather=dull;foo=bar', - "CGI::url()"); -test(17,$q->url(-absolute=>1) eq '/cgi-bin/foo.cgi','CGI::url(-absolute=>1)'); -test(18,$q->url(-relative=>1) eq 'foo.cgi','CGI::url(-relative=>1)'); -test(19,$q->url(-relative=>1,-path=>1) eq 'foo.cgi/somewhere/else','CGI::url(-relative=>1,-path=>1)'); -test(20,$q->url(-relative=>1,-path=>1,-query=>1) eq - 'foo.cgi/somewhere/else?game=chess;game=checkers;weather=dull;foo=bar', - 'CGI::url(-relative=>1,-path=>1,-query=>1)'); -$q->delete('foo'); -test(21,!$q->param('foo'),'CGI::delete()'); - -$q->_reset_globals; -$ENV{QUERY_STRING}='mary+had+a+little+lamb'; -test(22,$q=new CGI,"CGI::new() redux"); -test(23,join(' ',$q->keywords) eq 'mary had a little lamb','CGI::keywords'); -test(24,join(' ',$q->param('keywords')) eq 'mary had a little lamb','CGI::keywords'); -test(25,$q=new CGI('foo=bar&foo=baz'),"CGI::new() redux"); -test(26,$q->param('foo') eq 'bar','CGI::param() redux'); -test(27,$q=new CGI({'foo'=>'bar','bar'=>'froz'}),"CGI::new() redux 2"); -test(28,$q->param('bar') eq 'froz',"CGI::param() redux 2"); - -# test tied interface -my $p = $q->Vars; -test(29,$p->{bar} eq 'froz',"tied interface fetch"); -$p->{bar} = join("\0",qw(foo bar baz)); -test(30,join(' ',$q->param('bar')) eq 'foo bar baz','tied interface store'); -test(31,exists $p->{bar}); - -# test posting -$q->_reset_globals; -if ($Config{d_fork}) { - $test_string = 'game=soccer&game=baseball&weather=nice'; - $ENV{REQUEST_METHOD}='POST'; - $ENV{CONTENT_LENGTH}=length($test_string); - $ENV{QUERY_STRING}='big_balls=basketball&small_balls=golf'; - if (open(CHILD,"|-")) { # cparent - print CHILD $test_string; - close CHILD; - exit 0; - } - # at this point, we're in a new (child) process - test(32,$q=new CGI,"CGI::new() from POST"); - test(33,$q->param('weather') eq 'nice',"CGI::param() from POST"); - test(34,$q->url_param('big_balls') eq 'basketball',"CGI::url_param()"); -} else { - print "ok 32 # Skip\n"; - print "ok 33 # Skip\n"; - print "ok 34 # Skip\n"; -} diff --git a/ext/CGI/t/start_end_asterisk.t b/ext/CGI/t/start_end_asterisk.t deleted file mode 100644 index 0d67c9dae0..0000000000 --- a/ext/CGI/t/start_end_asterisk.t +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/local/bin/perl -w - -use lib qw(t/lib); -use strict; - -# Due to a bug in older versions of MakeMaker & Test::Harness, we must -# ensure the blib's are in @INC, else we might use the core CGI.pm -use lib qw(blib/lib blib/arch); -use Test::More tests => 45; - -use CGI qw(:standard *h1 *h2 *h3 *h4 *h5 *h6 *table *ul *li *ol *td *b *i *u *div); - -is(start_h1(), "<h1>", "start_h1"); # TEST -is(start_h1({class => 'hello'}), "<h1 class=\"hello\">", "start_h1 with param"); # TEST -is(end_h1(), "</h1>", "end_h1"); # TEST - -is(start_h2(), "<h2>", "start_h2"); # TEST -is(start_h2({class => 'hello'}), "<h2 class=\"hello\">", "start_h2 with param"); # TEST -is(end_h2(), "</h2>", "end_h2"); # TEST - -is(start_h3(), "<h3>", "start_h3"); # TEST -is(start_h3({class => 'hello'}), "<h3 class=\"hello\">", "start_h3 with param"); # TEST -is(end_h3(), "</h3>", "end_h3"); # TEST - -is(start_h4(), "<h4>", "start_h4"); # TEST -is(start_h4({class => 'hello'}), "<h4 class=\"hello\">", "start_h4 with param"); # TEST -is(end_h4(), "</h4>", "end_h4"); # TEST - -is(start_h5(), "<h5>", "start_h5"); # TEST -is(start_h5({class => 'hello'}), "<h5 class=\"hello\">", "start_h5 with param"); # TEST -is(end_h5(), "</h5>", "end_h5"); # TEST - -is(start_h6(), "<h6>", "start_h6"); # TEST -is(start_h6({class => 'hello'}), "<h6 class=\"hello\">", "start_h6 with param"); # TEST -is(end_h6(), "</h6>", "end_h6"); # TEST - -is(start_table(), "<table>", "start_table"); # TEST -is(start_table({class => 'hello'}), "<table class=\"hello\">", "start_table with param"); # TEST -is(end_table(), "</table>", "end_table"); # TEST - -is(start_ul(), "<ul>", "start_ul"); # TEST -is(start_ul({class => 'hello'}), "<ul class=\"hello\">", "start_ul with param"); # TEST -is(end_ul(), "</ul>", "end_ul"); # TEST - -is(start_li(), "<li>", "start_li"); # TEST -is(start_li({class => 'hello'}), "<li class=\"hello\">", "start_li with param"); # TEST -is(end_li(), "</li>", "end_li"); # TEST - -is(start_ol(), "<ol>", "start_ol"); # TEST -is(start_ol({class => 'hello'}), "<ol class=\"hello\">", "start_ol with param"); # TEST -is(end_ol(), "</ol>", "end_ol"); # TEST - -is(start_td(), "<td>", "start_td"); # TEST -is(start_td({class => 'hello'}), "<td class=\"hello\">", "start_td with param"); # TEST -is(end_td(), "</td>", "end_td"); # TEST - -is(start_b(), "<b>", "start_b"); # TEST -is(start_b({class => 'hello'}), "<b class=\"hello\">", "start_b with param"); # TEST -is(end_b(), "</b>", "end_b"); # TEST - -is(start_i(), "<i>", "start_i"); # TEST -is(start_i({class => 'hello'}), "<i class=\"hello\">", "start_i with param"); # TEST -is(end_i(), "</i>", "end_i"); # TEST - -is(start_u(), "<u>", "start_u"); # TEST -is(start_u({class => 'hello'}), "<u class=\"hello\">", "start_u with param"); # TEST -is(end_u(), "</u>", "end_u"); # TEST - -is(start_div(), "<div>", "start_div"); # TEST -is(start_div({class => 'hello'}), "<div class=\"hello\">", "start_div with param"); # TEST -is(end_div(), "</div>", "end_div"); # TEST - diff --git a/ext/CGI/t/start_end_end.t b/ext/CGI/t/start_end_end.t deleted file mode 100644 index 2eeed60c09..0000000000 --- a/ext/CGI/t/start_end_end.t +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/local/bin/perl -w - -use lib qw(t/lib); -use strict; - -# Due to a bug in older versions of MakeMaker & Test::Harness, we must -# ensure the blib's are in @INC, else we might use the core CGI.pm -use lib qw(blib/lib blib/arch); -use Test::More tests => 45; - -use CGI qw(:standard end_h1 end_h2 end_h3 end_h4 end_h5 end_h6 end_table end_ul end_li end_ol end_td end_b end_i end_u end_div); - -is(start_h1(), "<h1>", "start_h1"); # TEST -is(start_h1({class => 'hello'}), "<h1 class=\"hello\">", "start_h1 with param"); # TEST -is(end_h1(), "</h1>", "end_h1"); # TEST - -is(start_h2(), "<h2>", "start_h2"); # TEST -is(start_h2({class => 'hello'}), "<h2 class=\"hello\">", "start_h2 with param"); # TEST -is(end_h2(), "</h2>", "end_h2"); # TEST - -is(start_h3(), "<h3>", "start_h3"); # TEST -is(start_h3({class => 'hello'}), "<h3 class=\"hello\">", "start_h3 with param"); # TEST -is(end_h3(), "</h3>", "end_h3"); # TEST - -is(start_h4(), "<h4>", "start_h4"); # TEST -is(start_h4({class => 'hello'}), "<h4 class=\"hello\">", "start_h4 with param"); # TEST -is(end_h4(), "</h4>", "end_h4"); # TEST - -is(start_h5(), "<h5>", "start_h5"); # TEST -is(start_h5({class => 'hello'}), "<h5 class=\"hello\">", "start_h5 with param"); # TEST -is(end_h5(), "</h5>", "end_h5"); # TEST - -is(start_h6(), "<h6>", "start_h6"); # TEST -is(start_h6({class => 'hello'}), "<h6 class=\"hello\">", "start_h6 with param"); # TEST -is(end_h6(), "</h6>", "end_h6"); # TEST - -is(start_table(), "<table>", "start_table"); # TEST -is(start_table({class => 'hello'}), "<table class=\"hello\">", "start_table with param"); # TEST -is(end_table(), "</table>", "end_table"); # TEST - -is(start_ul(), "<ul>", "start_ul"); # TEST -is(start_ul({class => 'hello'}), "<ul class=\"hello\">", "start_ul with param"); # TEST -is(end_ul(), "</ul>", "end_ul"); # TEST - -is(start_li(), "<li>", "start_li"); # TEST -is(start_li({class => 'hello'}), "<li class=\"hello\">", "start_li with param"); # TEST -is(end_li(), "</li>", "end_li"); # TEST - -is(start_ol(), "<ol>", "start_ol"); # TEST -is(start_ol({class => 'hello'}), "<ol class=\"hello\">", "start_ol with param"); # TEST -is(end_ol(), "</ol>", "end_ol"); # TEST - -is(start_td(), "<td>", "start_td"); # TEST -is(start_td({class => 'hello'}), "<td class=\"hello\">", "start_td with param"); # TEST -is(end_td(), "</td>", "end_td"); # TEST - -is(start_b(), "<b>", "start_b"); # TEST -is(start_b({class => 'hello'}), "<b class=\"hello\">", "start_b with param"); # TEST -is(end_b(), "</b>", "end_b"); # TEST - -is(start_i(), "<i>", "start_i"); # TEST -is(start_i({class => 'hello'}), "<i class=\"hello\">", "start_i with param"); # TEST -is(end_i(), "</i>", "end_i"); # TEST - -is(start_u(), "<u>", "start_u"); # TEST -is(start_u({class => 'hello'}), "<u class=\"hello\">", "start_u with param"); # TEST -is(end_u(), "</u>", "end_u"); # TEST - -is(start_div(), "<div>", "start_div"); # TEST -is(start_div({class => 'hello'}), "<div class=\"hello\">", "start_div with param"); # TEST -is(end_div(), "</div>", "end_div"); # TEST - diff --git a/ext/CGI/t/start_end_start.t b/ext/CGI/t/start_end_start.t deleted file mode 100644 index 94768c1696..0000000000 --- a/ext/CGI/t/start_end_start.t +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/local/bin/perl -w - -use lib qw(t/lib); -use strict; - -# Due to a bug in older versions of MakeMaker & Test::Harness, we must -# ensure the blib's are in @INC, else we might use the core CGI.pm -use lib qw(blib/lib blib/arch); -use Test::More tests => 45; - -use CGI qw(:standard start_h1 start_h2 start_h3 start_h4 start_h5 start_h6 start_table start_ul start_li start_ol start_td start_b start_i start_u start_div); - -is(start_h1(), "<h1>", "start_h1"); # TEST -is(start_h1({class => 'hello'}), "<h1 class=\"hello\">", "start_h1 with param"); # TEST -is(end_h1(), "</h1>", "end_h1"); # TEST - -is(start_h2(), "<h2>", "start_h2"); # TEST -is(start_h2({class => 'hello'}), "<h2 class=\"hello\">", "start_h2 with param"); # TEST -is(end_h2(), "</h2>", "end_h2"); # TEST - -is(start_h3(), "<h3>", "start_h3"); # TEST -is(start_h3({class => 'hello'}), "<h3 class=\"hello\">", "start_h3 with param"); # TEST -is(end_h3(), "</h3>", "end_h3"); # TEST - -is(start_h4(), "<h4>", "start_h4"); # TEST -is(start_h4({class => 'hello'}), "<h4 class=\"hello\">", "start_h4 with param"); # TEST -is(end_h4(), "</h4>", "end_h4"); # TEST - -is(start_h5(), "<h5>", "start_h5"); # TEST -is(start_h5({class => 'hello'}), "<h5 class=\"hello\">", "start_h5 with param"); # TEST -is(end_h5(), "</h5>", "end_h5"); # TEST - -is(start_h6(), "<h6>", "start_h6"); # TEST -is(start_h6({class => 'hello'}), "<h6 class=\"hello\">", "start_h6 with param"); # TEST -is(end_h6(), "</h6>", "end_h6"); # TEST - -is(start_table(), "<table>", "start_table"); # TEST -is(start_table({class => 'hello'}), "<table class=\"hello\">", "start_table with param"); # TEST -is(end_table(), "</table>", "end_table"); # TEST - -is(start_ul(), "<ul>", "start_ul"); # TEST -is(start_ul({class => 'hello'}), "<ul class=\"hello\">", "start_ul with param"); # TEST -is(end_ul(), "</ul>", "end_ul"); # TEST - -is(start_li(), "<li>", "start_li"); # TEST -is(start_li({class => 'hello'}), "<li class=\"hello\">", "start_li with param"); # TEST -is(end_li(), "</li>", "end_li"); # TEST - -is(start_ol(), "<ol>", "start_ol"); # TEST -is(start_ol({class => 'hello'}), "<ol class=\"hello\">", "start_ol with param"); # TEST -is(end_ol(), "</ol>", "end_ol"); # TEST - -is(start_td(), "<td>", "start_td"); # TEST -is(start_td({class => 'hello'}), "<td class=\"hello\">", "start_td with param"); # TEST -is(end_td(), "</td>", "end_td"); # TEST - -is(start_b(), "<b>", "start_b"); # TEST -is(start_b({class => 'hello'}), "<b class=\"hello\">", "start_b with param"); # TEST -is(end_b(), "</b>", "end_b"); # TEST - -is(start_i(), "<i>", "start_i"); # TEST -is(start_i({class => 'hello'}), "<i class=\"hello\">", "start_i with param"); # TEST -is(end_i(), "</i>", "end_i"); # TEST - -is(start_u(), "<u>", "start_u"); # TEST -is(start_u({class => 'hello'}), "<u class=\"hello\">", "start_u with param"); # TEST -is(end_u(), "</u>", "end_u"); # TEST - -is(start_div(), "<div>", "start_div"); # TEST -is(start_div({class => 'hello'}), "<div class=\"hello\">", "start_div with param"); # TEST -is(end_div(), "</div>", "end_div"); # TEST - diff --git a/ext/CGI/t/switch.t b/ext/CGI/t/switch.t deleted file mode 100644 index ac58618a7f..0000000000 --- a/ext/CGI/t/switch.t +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/local/bin/perl -w - -use lib qw(t/lib); - -# Due to a bug in older versions of MakeMaker & Test::Harness, we must -# ensure the blib's are in @INC, else we might use the core CGI.pm -use lib qw(blib/lib blib/arch); - -use strict; -use Test::More tests => 1; - -# Can't do much with this other than make sure it loads properly -BEGIN { use_ok('CGI::Switch') }; diff --git a/ext/CGI/t/unescapeHTML.t b/ext/CGI/t/unescapeHTML.t deleted file mode 100644 index fc0f750f0c..0000000000 --- a/ext/CGI/t/unescapeHTML.t +++ /dev/null @@ -1,11 +0,0 @@ -use lib 't/lib'; -use Test::More 'no_plan'; -use CGI 'unescapeHTML'; - -is( unescapeHTML( '&'), '&', 'unescapeHTML: &'); -is( unescapeHTML( '"'), '"', 'unescapeHTML: "'); -TODO: { - local $TODO = 'waiting on patch. Reference: https://rt.cpan.org/Ticket/Display.html?id=39122'; - is( unescapeHTML( 'Bob & Tom went to the store; Where did you go?'), - 'Bob & Tom went to the store; Where did you go?', 'unescapeHTML: a case where &...; should not be escaped.'); -} diff --git a/ext/CGI/t/upload.t b/ext/CGI/t/upload.t deleted file mode 100644 index 0989f1d560..0000000000 --- a/ext/CGI/t/upload.t +++ /dev/null @@ -1,151 +0,0 @@ -#!/usr/local/bin/perl -w - -################################################################# -# Emanuele Zeppieri, Mark Stosberg # -# Shamelessly stolen from Data::FormValidator and CGI::Upload # -################################################################# - -# Due to a bug in older versions of MakeMaker & Test::Harness, we must -# ensure the blib's are in @INC, else we might use the core CGI.pm -use lib qw(. ./blib/lib ./blib/arch); - -use strict; - -use Test::More 'no_plan'; - -use CGI; - -#----------------------------------------------------------------------------- -# %ENV setup. -#----------------------------------------------------------------------------- - -my %myenv; - -BEGIN { - %myenv = ( - 'SCRIPT_NAME' => '/test.cgi', - 'SERVER_NAME' => 'perl.org', - 'HTTP_CONNECTION' => 'TE, close', - 'REQUEST_METHOD' => 'POST', - 'SCRIPT_URI' => 'http://www.perl.org/test.cgi', - 'CONTENT_LENGTH' => 3285, - 'SCRIPT_FILENAME' => '/home/usr/test.cgi', - 'SERVER_SOFTWARE' => 'Apache/1.3.27 (Unix) ', - 'HTTP_TE' => 'deflate,gzip;q=0.3', - 'QUERY_STRING' => '', - 'REMOTE_PORT' => '1855', - 'HTTP_USER_AGENT' => 'Mozilla/5.0 (compatible; Konqueror/2.1.1; X11)', - 'SERVER_PORT' => '80', - 'REMOTE_ADDR' => '127.0.0.1', - 'CONTENT_TYPE' => 'multipart/form-data; boundary=xYzZY', - 'SERVER_PROTOCOL' => 'HTTP/1.1', - 'PATH' => '/usr/local/bin:/usr/bin:/bin', - 'REQUEST_URI' => '/test.cgi', - 'GATEWAY_INTERFACE' => 'CGI/1.1', - 'SCRIPT_URL' => '/test.cgi', - 'SERVER_ADDR' => '127.0.0.1', - 'DOCUMENT_ROOT' => '/home/develop', - 'HTTP_HOST' => 'www.perl.org' - ); - - for my $key (keys %myenv) { - $ENV{$key} = $myenv{$key}; - } -} - -END { - for my $key (keys %myenv) { - delete $ENV{$key}; - } -} - -#----------------------------------------------------------------------------- -# Simulate the upload (really, multiple uploads contained in a single stream). -#----------------------------------------------------------------------------- - -my $q; - -{ - local *STDIN; - open STDIN, '<t/upload_post_text.txt' - or die 'missing test file t/upload_post_text.txt'; - binmode STDIN; - $q = CGI->new; -} - -#----------------------------------------------------------------------------- -# Check that the file names retrieved by CGI are correct. -#----------------------------------------------------------------------------- - -is( $q->param('does_not_exist_gif'), 'does_not_exist.gif', 'filename_2' ); -is( $q->param('100;100_gif') , '100;100.gif' , 'filename_3' ); -is( $q->param('300x300_gif') , '300x300.gif' , 'filename_4' ); - -{ - my $test = "multiple file names are handled right with same-named upload fields"; - my @hello_names = $q->param('hello_world'); - is ($hello_names[0],'goodbye_world.txt',$test. "...first file"); - is ($hello_names[1],'hello_world.txt',$test. "...second file"); -} - -#----------------------------------------------------------------------------- -# Now check that the upload method works. -#----------------------------------------------------------------------------- - -ok( defined $q->upload('does_not_exist_gif'), 'upload_basic_2' ); -ok( defined $q->upload('100;100_gif') , 'upload_basic_3' ); -ok( defined $q->upload('300x300_gif') , 'upload_basic_4' ); - -{ - my $test = "file handles have expected length for multi-valued field. "; - my ($goodbye_fh,$hello_fh) = $q->upload('hello_world'); - - # Go to end of file; - seek($goodbye_fh,0,2); - # How long is the file? - is(tell($goodbye_fh), 15, "$test..first file"); - - # Go to end of file; - seek($hello_fh,0,2); - # How long is the file? - is(tell($hello_fh), 13, "$test..second file"); - -} - - - -{ - my $test = "300x300_gif has expected length"; - my $fh1 = $q->upload('300x300_gif'); - is(tell($fh1), 0, "First object: filehandle starts with position set at zero"); - - # Go to end of file; - seek($fh1,0,2); - # How long is the file? - is(tell($fh1), 1656, $test); -} - -my $q2 = CGI->new; - -{ - my $test = "Upload filehandles still work after calling CGI->new a second time"; - $q->param('new','zoo'); - - is($q2->param('new'),undef, - "Reality Check: params set in one object instance don't appear in another instance"); - - my $fh2 = $q2->upload('300x300_gif'); - is(tell($fh2), 0, "...so the state of a file handle shouldn't be carried to a new object instance, either."); - # Go to end of file; - seek($fh2,0,2); - # How long is the file? - is(tell($fh2), 1656, $test); -} - -{ - my $test = "multi-valued uploads are reset properly"; - my ($dont_care, $hello_fh2) = $q2->upload('hello_world'); - is(tell($hello_fh2), 0, $test); -} - -# vim: nospell diff --git a/ext/CGI/t/uploadInfo.t b/ext/CGI/t/uploadInfo.t deleted file mode 100644 index 970429b8bb..0000000000 --- a/ext/CGI/t/uploadInfo.t +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/local/bin/perl -w - -################################################################# -# Emanuele Zeppieri, Mark Stosberg # -# Shamelessly stolen from Data::FormValidator and CGI::Upload # -################################################################# - -# Due to a bug in older versions of MakeMaker & Test::Harness, we must -# ensure the blib's are in @INC, else we might use the core CGI.pm -use lib qw(. ./blib/lib ./blib/arch); - -use strict; - -use Test::More 'no_plan'; - -use CGI; - -#----------------------------------------------------------------------------- -# %ENV setup. -#----------------------------------------------------------------------------- - -my %myenv; - -BEGIN { - %myenv = ( - 'SCRIPT_NAME' => '/test.cgi', - 'SERVER_NAME' => 'perl.org', - 'HTTP_CONNECTION' => 'TE, close', - 'REQUEST_METHOD' => 'POST', - 'SCRIPT_URI' => 'http://www.perl.org/test.cgi', - 'CONTENT_LENGTH' => 3285, - 'SCRIPT_FILENAME' => '/home/usr/test.cgi', - 'SERVER_SOFTWARE' => 'Apache/1.3.27 (Unix) ', - 'HTTP_TE' => 'deflate,gzip;q=0.3', - 'QUERY_STRING' => '', - 'REMOTE_PORT' => '1855', - 'HTTP_USER_AGENT' => 'Mozilla/5.0 (compatible; Konqueror/2.1.1; X11)', - 'SERVER_PORT' => '80', - 'REMOTE_ADDR' => '127.0.0.1', - 'CONTENT_TYPE' => 'multipart/form-data; boundary=xYzZY', - 'SERVER_PROTOCOL' => 'HTTP/1.1', - 'PATH' => '/usr/local/bin:/usr/bin:/bin', - 'REQUEST_URI' => '/test.cgi', - 'GATEWAY_INTERFACE' => 'CGI/1.1', - 'SCRIPT_URL' => '/test.cgi', - 'SERVER_ADDR' => '127.0.0.1', - 'DOCUMENT_ROOT' => '/home/develop', - 'HTTP_HOST' => 'www.perl.org' - ); - - for my $key (keys %myenv) { - $ENV{$key} = $myenv{$key}; - } -} - -END { - for my $key (keys %myenv) { - delete $ENV{$key}; - } -} - - -#----------------------------------------------------------------------------- -# Simulate the upload (really, multiple uploads contained in a single stream). -#----------------------------------------------------------------------------- - -my $q; - -{ - local *STDIN; - open STDIN, '<t/upload_post_text.txt' - or die 'missing test file t/upload_post_text.txt'; - binmode STDIN; - $q = CGI->new; -} - -{ - my $test = "uploadInfo: basic test"; - my $fh = $q->upload('300x300_gif'); - is( $q->uploadInfo($fh)->{'Content-Type'}, "image/gif", $test); -} - -my $q2 = CGI->new; - -{ - my $test = "uploadInfo: works with second object instance"; - my $fh = $q2->upload('300x300_gif'); - is( $q2->uploadInfo($fh)->{'Content-Type'}, "image/gif", $test); -} - diff --git a/ext/CGI/t/upload_post_text.txt b/ext/CGI/t/upload_post_text.txt Binary files differdeleted file mode 100644 index 91393f064c..0000000000 --- a/ext/CGI/t/upload_post_text.txt +++ /dev/null diff --git a/ext/CGI/t/user_agent.t b/ext/CGI/t/user_agent.t deleted file mode 100644 index 1a4880dc7c..0000000000 --- a/ext/CGI/t/user_agent.t +++ /dev/null @@ -1,15 +0,0 @@ -# Test the user_agent method. -use lib 't/lib'; -use Test::More 'no_plan'; -use CGI; - -my $q = CGI->new; - -is($q->user_agent, undef, 'user_agent: undef test'); - -$ENV{HTTP_USER_AGENT} = 'mark'; -is($q->user_agent, 'mark', 'user_agent: basic test'); -ok($q->user_agent('ma.*'), 'user_agent: positive regex test'); -ok(!$q->user_agent('BOOM.*'), 'user_agent: negative regex test'); - - diff --git a/ext/CGI/t/util-58.t b/ext/CGI/t/util-58.t deleted file mode 100644 index 75c0ea9723..0000000000 --- a/ext/CGI/t/util-58.t +++ /dev/null @@ -1,29 +0,0 @@ -# test CGI::Util::escape -use Test::More tests => 4; -use_ok("CGI::Util"); - -# Byte strings should be escaped byte by byte: -# 1) not a valid utf-8 sequence: -my $uri = "pe\x{f8}\x{ed}\x{e8}ko.ogg"; -is(CGI::Util::escape($uri), "pe%F8%ED%E8ko.ogg", "Escape a Latin-2 string"); - -# 2) is a valid utf-8 sequence, but not an UTF-8-flagged string -# This happens often: people write utf-8 strings to source, but forget -# to tell perl about it by "use utf8;"--this is obviously wrong, but we -# have to handle it gracefully, for compatibility with GCI.pm under -# perl-5.8.x -# -$uri = "pe\x{c5}\x{99}\x{c3}\x{ad}\x{c4}\x{8d}ko.ogg"; -is(CGI::Util::escape($uri), "pe%C5%99%C3%AD%C4%8Dko.ogg", - "Escape an utf-8 byte string"); - -SKIP: -{ - # This tests CGI::Util::escape() when fed with UTF-8-flagged string - # -- dankogai - skip("Unicode strings not available in $]", 1) if ($] < 5.008); - $uri = "\x{5c0f}\x{98fc} \x{5f3e}.txt"; # KOGAI, Dan, in Kanji - is(CGI::Util::escape($uri), "%E5%B0%8F%E9%A3%BC%20%E5%BC%BE.txt", - "Escape string with UTF-8 flag"); -} -__END__ diff --git a/ext/CGI/t/util.t b/ext/CGI/t/util.t deleted file mode 100644 index 702a4695d6..0000000000 --- a/ext/CGI/t/util.t +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/local/bin/perl -w - -# Test ability to escape() and unescape() punctuation characters -# except for qw(- . _). -######################### We start with some black magic to print on failure. -use lib '../blib/lib','../blib/arch'; - -BEGIN {$| = 1; print "1..57\n"; } -END {print "not ok 1\n" unless $loaded;} -use Config; -use CGI::Util qw(escape unescape); -$loaded = 1; -print "ok 1\n"; - -######################### End of black magic. - -# util -sub test { - local($^W) = 0; - my($num, $true,$msg) = @_; - print($true ? "ok $num\n" : "not ok $num $msg\n"); -} - -# ASCII order, ASCII codepoints, ASCII repertoire - -my %punct = ( - ' ' => '20', '!' => '21', '"' => '22', '#' => '23', - '$' => '24', '%' => '25', '&' => '26', '\'' => '27', - '(' => '28', ')' => '29', '*' => '2A', '+' => '2B', - ',' => '2C', '/' => '2F', # '-' => '2D', '.' => '2E' - ':' => '3A', ';' => '3B', '<' => '3C', '=' => '3D', - '>' => '3E', '?' => '3F', '[' => '5B', '\\' => '5C', - ']' => '5D', '^' => '5E', '`' => '60', # '_' => '5F', - '{' => '7B', '|' => '7C', '}' => '7D', # '~' => '7E', - ); - -# The sort order may not be ASCII on EBCDIC machines: - -my $i = 1; - -foreach(sort(keys(%punct))) { - $i++; - my $escape = "AbC\%$punct{$_}dEF"; - my $cgi_escape = escape("AbC$_" . "dEF"); - test($i, $escape eq $cgi_escape , "# $escape ne $cgi_escape"); - $i++; - my $unescape = "AbC$_" . "dEF"; - my $cgi_unescape = unescape("AbC\%$punct{$_}dEF"); - test($i, $unescape eq $cgi_unescape , "# $unescape ne $cgi_unescape"); -} - |