Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I've been trying my hardest to get this CGI to work. I am trying to make a webpage from the information that is submitted via a form or web link, such as using www.cheese.com/foo?node=Gouda and it is then sent to the CGI file where it is decoded and marked up in the appropriate way. Here is what I have so far.
#!usr/bin/perl if ($ENV{'REQUEST_METHOD'} eq 'GET') { #Check to see which one it is $Good_Stuff = $ENV{'QUERY_STRING'}; #Split up the information } elsif ($ENV{'REQUEST_METHOD'} eq 'POST') { read(STDIN, $Good_Stuff, $ENV{'CONTENT_LENGTH'}); } ($Name, $Image) = split(/=/, $Good_Stuff); #Split up more stuff @Stuff = split(/%2F/, $Image); #This will split up the file into to pa +rts $Final = join('/', @Stuff); #Join it together for something that is wh +ole #Print out lots of stuff (this never works, though). print "Content-type: text/html\n\n"; print "<HTML><HEAD>\n"; print <<ENDMETA; <META NAME="GENERATOR" CONTENT="Adobe PageMill 3.0 Win"> <TITLE>Animetion Station &gt; Webcomic &gt; $Name</title> <LINK REL="stylesheet" HREF="Style.css" TYPE="text/css"> ENDMETA print "</head><BODY>\n"; print <<ENDHTML; <P><CENTER><DIV STYLE="background-color: #0099FF; font-family: Comic S +ans MS; font-size: 20px; width: 200px; color: white;">Web Comics</div></center></p> <P><TABLE WIDTH="757" BORDER="0" CELLSPACING="1" CELLPADDING="0" HEIGHT="294"> <TR> <TD WIDTH="14%" VALIGN="TOP" ALIGN="CENTER" HEIGHT="293"> <!--#include file="Sidebar.txt"--> </td> <TD WIDTH="86%" VALIGN="TOP" BGCOLOR="#3366ff"> <P><IMG SRC="$Final"></p> <P><IMG SRC="Images/Comic_Face.jpg" WIDTH="57" HEIGHT="54" ALIGN="BOTTOM" BORDER="0" NATURALSIZEFLAG="3"> <IMG SRC="Images/Co +mic_Face2.jpg" WIDTH="60" HEIGHT="55" ALIGN="BOTTOM" BORDER="0" NATURALSIZEFLAG=" +3"> <IMG SRC="Images/Comic_Face3.jpg" WIDTH="60" HEIGHT="62" ALIGN="BOTTOM" BORDER="0" NATURALSIZEFLAG="3"> <IMG SRC="Images/Co +mic_Face4.jpg" WIDTH="60" HEIGHT="60" ALIGN="BOTTOM" BORDER="0" NATURALSIZEFLAG=" +3"></td> </tr> </table> ENDHTML print "</body></html>\n";
I would like a user to input the data from a form or web link and get the image or information is needed. I made this so that a person doesn't have to click through too many webpages and it saves on writing code. Could you help me?

Replies are listed 'Best First'.
Re: Making webpages from a single CGI
by mr_dont (Beadle) on Oct 04, 2001 at 01:27 UTC

    The most obvious advice i can give is to use the glorious perl CGI.pm module. This module comes with the standard distribution of perl and should be available on your machine...

    To get at your variables, try something like:

    #!/usr/bin/perl # Loads the CGI Module use CGI; # creates a new CGI object my $page = new CGI; # This will print a standard HTML header print $page->header; # Grab a named CGI parameter # CGI::pm automatically figures out # if it's sent by GET or POST my $value = $page->param('node'); # Then: print "<html><head><title>node is $value</title></head>\n"; print "<body> Hi, you are on the $value node!</body></html>\n";

    There are many more features to this great module. Learn about this before you do any other CGI programming.

      ooops, line breaks would be nice
Re: Making webpages from a single CGI
by C-Keen (Monk) on Oct 04, 2001 at 00:39 UTC
    As stated before here it is easier done with the CGI module. Do a search at CPAN for CGI or just do a perldoc CGI since this module usually comes with perl.

    Hope this helps,
    C-Keen

(jeffa) Re: Making webpages from a single CGI
by jeffa (Bishop) on Oct 04, 2001 at 02:01 UTC
    Here is another way to use CGI - i assume that all images will be stored in a doc_root directory named 'images', and only .png images files are used:
    use strict; use CGI qw(:standard); my $image; print header, start_html, start_form, textfield('image'), submit, end_form, hr, p; if ($image = param('image')) { $image .= '.png' unless $image =~ /\.png$/; print img { src => "/images/$image"}; } print p, hr, end_html;

    jeffa

Re: Making webpages from a single CGI
by Zecho (Hermit) on Oct 04, 2001 at 02:01 UTC
    First, your use of ReadParse was a little over the top
    Second when you want to print a block of html, use "s if you want to interpolate and 's if not.
    Third, use strict and warnings.. They will give you a lot of answers on their own

    The following works fine if the request is something like
    http://foo.com/bar.cgi?baz=image.jpg
    #!/usr/bin/perl -w use strict; my $Final; my $Good_Stuff; if ($ENV{'REQUEST_METHOD'} eq 'GET') { #Check to see which one it is $Good_Stuff = $ENV{'QUERY_STRING'}; #Split up the information } elsif ($ENV{'REQUEST_METHOD'} eq 'POST') { read(STDIN, $Good_Stuff, $ENV{'CONTENT_LENGTH'}); } ($Final) = split(/=/, $Good_Stuff,1); #Grab the filename $Final =~ s/%(..)/pack("c",hex($1))/ge; #Just for fun #Print out lots of stuff (this never works, though). print "Content-type: text/html\n\n"; print <<'ENDMETA'; <HTML><HEAD> <META NAME="GENERATOR" CONTENT="Adobe PageMill 3.0 Win"> <TITLE>Animetion Station &gt; Webcomic &gt; $Name</title> <LINK REL="stylesheet" HREF="Style.css" TYPE="text/css"> </head> ENDMETA print <<"ENDHTML"; <BODY> <P><CENTER> <DIV STYLE="background-color: #0099FF; font-family: Comic Sans MS; fon +t-size: 20px; width: 200px; color: white;"> Web Comics</div></center></p> <P> <TABLE WIDTH="757" BORDER="0" CELLSPACING="1" CELLPADDING="0" HEIGHT=" +294"> <TR> <TD WIDTH="14%" VALIGN="TOP" ALIGN="CENTER" HEIGHT="293"> <!--#include file="Sidebar.txt"--> </td> <TD WIDTH="86%" VALIGN="TOP" BGCOLOR="#3366ff"> <P><IMG SRC="$Final"></p> <P><IMG SRC="Images/Comic_Face.jpg" WIDTH="57" HEIGHT="54" ALIGN="BOTT +OM" BORDER="0" NATURALSIZEFLAG="3"> <IMG SRC="Images/Comic_Face2.jpg" WIDTH="60" HEIGHT="55" ALIGN="BOTTOM +" BORDER="0" NATURALSIZEFLAG="3"> <IMG SRC="Images/Comic_Face3.jpg" WIDTH="60" HEIGHT="62" ALIGN="BOTTOM +" BORDER="0" NATURALSIZEFLAG="3"> <IMG SRC="Images/Comic_Face4.jpg" WIDTH="60" HEIGHT="60" ALIGN="BOTTOM +" BORDER="0" NATURALSIZEFLAG="3"></td> </tr> </table> </body></html> ENDHTML
      The following works fine if the request is something like http://foo.com/bar.cgi?baz=image.jpg

      What if the request is something like http://www.cheese.com/foo?file=image.jpg%22%3E%3C!--%20#include%0Afile=%22/etc/passwd%22--%3E%3Cspan%20id=%22foo

      Alright, I'm picking on you for comments like "This never works" and "Just for fun". If you're not sure what something does, please find out before you recommend it to someone else.

      Using CGI.pm will not fix the exploitish URI above, though it will prevent you from hand rolling form parsing code. Reading through perldoc perlsec won't automatically fix the potential security hole, but it will help you think in terms of how to minimize the risk. ©

        Actually, I was attempting to stick with his original code and comments, as well as his original request. Yes obviously there is more to parsing query strings, and that should be something he investigates. I was just attempting to fix what he had already written
Re: Making webpages from a single CGI
by Anonymous Monk on Oct 04, 2001 at 06:06 UTC
    After you get the param info (from using CGI.pm, of course), if you wanted to execute a particular sub based on a param, you could do something like this (untested):

    my %nodes = ( 'page1' => \&home, 'something' => \&something, 'another' => \&another ); ##later on... ##stolen from The Perl Cookbook ##assuming that page wanted is in $current_screen while(my ($wanted_screen, $function) = each %nodes) { $function->($wanted_screen eq $current_screen); } sub page1($) { my $active = shift; ##do stuff here based on whether its active or not } ##declare other subs here, taking a true or false value as an arg as s +hown above
    Sorry if this seems too offtopic, but I found it very helpful in situations like yours. Also note that appropiate function is called the way above instead of a simpler way so that if you needed to keep smacking hidden values into the html of your page that are called as params too, you can do it every time the script is invoked.

    Hope it helps!!
Re: Making webpages from a single CGI
by Anonymous Monk on Oct 04, 2001 at 02:00 UTC
    Oh thank you, oh great thinkers! I can now make a great web page without using too much HTML!
      The easiest way to not have HTML in the script is to use HTML::Template It allows you to set up tags in a separate template file (consiting of HTML) and will then insert the values you want into it. Even does loops and if blocks. Very fast and easy to use.
Re: Making webpages from a single CGI
by scottvr (Initiate) on Oct 05, 2001 at 06:34 UTC
    one real quick further comment on this, just so the guy doesn't get too confused when it still doesn't do what he wants it to 100%... that SSI you have in there that reads in sidebar.txt is also of course designed to save on writing code.. Thing is, you probably want to go ahead and just paste the contents of that file into your CGI script as well since your '<!--#include' will never bee "seen" by the webserver daemon and thus won't get parsed.. From the question and the (seemingly) superfluous inclusion of Adobe PageMill's meta tag, I figured you might not be too familiar with what all was going on in that file so that when you got it working according to the other suggestions, you might be posting here again with a "it works but..." :) Hope that's useful to you. --ScottVR