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

I'm a newbie in Perl... I'm trying to make an interface to a website so that the address in the url will look something like.. http://lezar.org/?Front for the main page http://lezar.org/?WebMail for the WebMail and so on... the script I made keeps making and error and I don't know how to debug it... so here it is maybe someone can help me.. ___________________________________________________
#!/usr/bin/perl $where = $ENV{'QUERY_STRING'}; if ($where eq 'Front') { print "Content-type: text/html\n\n"; print <<Mn; <HTML> <head> <title>Lezar.org</title> </head> <body bgcolor="#FFFFFF" text="#000000" link="#666666" vlink="#666666" +alink="#666666" style="overflow: hidden"> <table width="100%" height="100%"> <tr height="100%"> <td width="100%"> <div align="center"> <pre>Lezar.org<br><br>Coming soon</pre> <font size="1" face="Verdana, Arial, Helvetica, sans-serif">for inform +ation contact <a href="mailto:info\@lezar.org">info\@lezar.org</a></font></d +iv> </table> </body></HTML> Mn } elsif ($where eq 'WebMail') { print "Content-type: text/html\n\n"; print <<WbMl; <HTML> <head> <title>Lezar.org</title> </head> <body> <script language="JavaScript"> <!-- self.location = "http://lezar.virtualave.net/WebMail"; //--> </script> </body> </html> WbMl } #
___________________________________________________ thanx in advance

Replies are listed 'Best First'.
(Ovid) Re: Stuck
by Ovid (Cardinal) on Dec 16, 2000 at 01:44 UTC
    Update: ctweten pointed out that your URL is definitely legal. Thanks!

    To be honest, I'm not sure that you're URL is legal. Try a url like the following:

    http://lezar.org/path/to/script/myscript?where=someval
    /path/to/script/myscript should be the path and name of your script. where=somval is a name value pair that gets passed to the query string.

    Then, use CGI to get the name/value pairs. You also shoudl use taint checking (that's the -T switch on the shebang line) and use strict to catch all sorts of problems. Here's an updated version of what you want to do:

    #!/usr/bin/perl -wT use strict; use CGI qw/:standard/; my $taintedWhere = param( 'where' ); my $where = ( $taintedWhere =~ /(\w+)/ ); if ( $where eq 'Front' ) { print header; print <<" Mn"; Some HTML Mn } elsif ( $where eq 'WebMail' ) { print header; print <<" WbMl"; Some more HTML WbMl } else { # $where is not what we expect, so we have an error routine here; }
    See perlsec for information on the security issues and you can also check out my online CGI course for further information. It's not complete, but it should give you a good start.

    For easier debugging, try adding the following line to your script:

    use CGI::Carp qw( fatalsToBrowser );
    That will usually print useful debugging information to the browser. Just make sure that you remove this when you put the script on a production server! There's no sense proving crackers with additional information about how your script works.

    Cheers,
    Ovid

    Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

      Just out of curiosity, why are you worried about un-tainting $where if you're just using it for comparisons and no system operations? Or is this just a safety net in the event the original poster does wish to use $where in a risky way?
        That's a good question and it's just indicative of paranoia on my part. I tend to untaint data regardless of how it's going to be used at the present time. I don't know who will be maintaining my work in the future and what they're going to be doing with it, so rather than take any chances, I'd like to cover that up front. It's the same reason I turned on taint checking when it's not needed -- I never know who will use this script in the future.

        Good question, though. It's a matter of style. I just prefer to be ultra paranoid -- after all, they're watching me ;)

        Cheers,
        Ovid

        Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

      FYI, that URL is most deffinitley legal. OTOH, I like your code much better.
      --
      Casey
         I am a superhero.
      
Re: Stuck
by davorg (Chancellor) on Dec 16, 2000 at 01:40 UTC

    What is the error that you get? Have you tried running the script from the command line?

    Adding -w and use strict; to the script only throws up one small error, which is simple enough to fix (my $where;). Other than that, your Perl seems inelegant, but functional.

    Maybe it is a problem with the way your web server is set up. Telling us the exact error would help us to help you.

    --
    <http://www.dave.org.uk>

    "Perl makes the fun jobs fun
    and the boring jobs bearable" - me

Re: Stuck
by damian1301 (Curate) on Dec 16, 2000 at 02:12 UTC
    In fact I was doing the same peice of coding a while ago and came up with something similarly simple and elegant. Well without delay here it is. It captures the referrer and logs it.
    #!/usr/bin/perl use CGI qw(param standard); use strict; my $query = new CGI; my $referrer = $query->param("ref"); my $location = $query->param("place"); print $query->header; if ($referrer){ $referrer =~ tr/A-Z/a-z/; open(REF, ">>referrer.txt") or default('Cant open/write, $!'); print REF "$referrer\n"; close(REF); }elsif ($ENV{'HTTP_REFERER'}) { open(REF1, ">>referrer.txt") or default('Cant open/write, $!'); print REF1 "$ENV{'HTTP_REFERER'}\n"; close(REF1); } if (!$location){ &main }elsif (lc($location) eq "misc"){ &misc }elsif (lc($location) eq "links"){ &links }else{ default('Where are you trying to go?'); } sub links{ print "links\n"; } sub misc{ print "misc\n"; } sub default{ print "Theres an error: @_"; } sub main{ print "this is sub main!"; }


    Wanna be perl hacker.
    Dave AKA damian
Re: Stuck
by c-era (Curate) on Dec 16, 2000 at 01:38 UTC
    First off, you should use CGI, this will be very helpful to you. Also, if you insist on doing it this way (which you shouldn't) you can print out $where to see what it contains.

      You should absolutely print out $where -- I thought for a moment that $ENV{'QUERY_STRING'} might also return the '?' but a quick test showed that no, it doesn't. Nevertheless, you might have a zero-space character after "Front" that is preventing the match and unless you print it out, you'll never know.

      On a progammatic note, if you insist on writing our own output code and not using CGI, you should try to look form ways to reduce the duplication that is apparent in your code.

      For instance, both sections clearly output the content-type and some basic header information, so why is that wrapped up in your if/else statement?

      A good rule of thumb is that whenever you find yourself typing the exact same thing two or more times in a switch/subroutine sequence, you've probably got the switch/sub in the wrong place or it contains the wrong stuff.

Re: Stuck
by cwest (Friar) on Dec 16, 2000 at 01:44 UTC
    Without any idea of what the error could possibly be, without one little piece of information about what happens when you try to run this program or how you try to run this program I'm going o say that I don't have a friggin clue what's wrong!

    Next, if you're actually trying to access this page from the web browser and you're getting a 500 error, I suggest:

    • Review the web logs ( tail LOG_FILE , where LOG_FILE is a path to the log file which could be anywhere ).
    • put use CGI::Carp qw(fatalsToBrowser); after your #! line.
    • Run the program from the command line and watch the output.
    Note: I ran this program locally without any trouble. In light of that, I would also: check permissions, make sure it's in the right place, try running it from the command line, make sure your web server is set up to run Perl programs, * ( read: c'mon man, give me a clue! ).
    --
    Casey
       I am a superhero.
    
Re: Stuck
by Fastolfe (Vicar) on Dec 16, 2000 at 06:05 UTC
    I'm not going to repeat what others have said on this thread, but in the event you want to explore other ways of writing your URL's, consider using the PATH_INFO variable. This would let you construct traditional-looking URL's that are really comprised of script arguments:
    http://www.example.com/one/two/three/four.html
    You could create a script called 'one' in the web server's docroot, and your script would receive the following in its $ENV{PATH_INFO}:
    /two/three/four.html
    You could even go a step further and use this in conjunction with typical CGI arguments:
    http://www.example.com/one/two.html?arg1=one&arg2=two $ENV{PATH_INFO} is "/one/two.html" $ENV{QUERY_STRING} is "arg1=one&arg2=two"
    CGI.pm will do all of this for you in a friendly fashion.
      There is at least one case I know of where you don't really have a choice about using PATH_INFO.

      If you want to download a file on the fly to be read by Excel, with IE 4 and some versions of Excel it will break horribly if IE knows that it is dealing with a CGI script. The only workaround I know of is to hide the fact of a CGI script using PATH_INFO. (The actual bug is that the path to the temp file is split on spaces before being passed to Excel. Since that path often has "Temporary Internet Files" in it, this results in Excel not finding the temporary file with your data.)

      Ok... so I didn't expect such a quick reply from you guys.. thanx a lot..
      the problem is with my server I guess... I checked all the variables in the %ENV hash.. only the QUERY_STRING apprears empty, I don't know why..
      and you guys who are telling me that it has repetitions.. I already know that.. and as you know I'm just testing..
      viewing the log?? I tried it.. it says no recent errors so that's why I don't know what is happening... I want to know if there is a utility for Perl offline like the PWS for the .asp
      and I said I am a newbie, so I don't know how to use CGI.pm
      I hope it works.. or else i will switch to JavaScript
Re: Stuck
by jynx (Priest) on Dec 16, 2000 at 01:43 UTC
    well,

    This probably won't be as much help as you want, but you'll hear it quite often if you get into perl significantly. Try not to reinvent the wheel when it doesn't need it. There are two major things about your code that i would change (imho):

    First of all, you're printing the same things multiple times, if you are absolutely going to be having the same title, print it once at the top of your page and save the if...elsif...else statements for code that will change. This will help simplify where your errors are by breaking up your coding blocks into manageable pieces as well.

    Secondly, try looking into CGI.pm (from CPAN) to do the parsing for you. While it is interesting to know what needs to printed on a web page, and is good practice for understanding things, if you don't need to do it, don't. CGI will do most of that for you.

    These are just my 2 cents worth, hope it works out,

    jynx

Re: Stuck
by tune (Curate) on Dec 16, 2000 at 01:52 UTC
    Insert this line into your code after the #!/usr/bin/perl:

    use CGI; use CGI::Carp 'fatalsToBrowser';
    This will print the error messages into your browser window, and you can find out what the problem is.

    -- tune

Re: Stuck
by Chady (Priest) on Dec 16, 2000 at 15:26 UTC
    That's me the Anonymous Monk now with a name... I tried to test the variables, it seems that the server is not getting the QUERY_STRING so I tried HTTP_REFERER, still with an error..
    #!/usr/bin/perl @all = split(/?/,$ENV{'HTTP_REFERER'}); $where = @all[1]; if ($where eq 'Front') { print "Content-type: text/html\n\n"; print <<Mn; <HTML> <head> <title>Lezar.org</title> </head> <body bgcolor="#FFFFFF" text="#000000" link="#666666" vlink="#666666" +alink="#666666" style="overflow: hidden"> <table width="100%" height="100%"> <tr height="100%"> <td width="100%"> <div align="center"> <pre>Lezar.org<br><br>Coming soon</pre> <font size="1" face="Verdana, Arial, Helvetica, sans-serif">for inform +ation contact <a href="mailto:info\@lezar.org">info\@lezar.org</a></font></d +iv> </table> </body></HTML> Mn } elsif ($where eq 'WebMail') { print "Content-type: text/html\n\n"; print <<WbMl; <HTML> <head> <title>Lezar.org</title> </head> <body> <script language="JavaScript"> <!-- self.location = "http://lezar.virtualave.net/WebMail"; //--> </script> </body> </html> WbMl } else { print "Content-type: text/html\n\n"; print "Query String is : $where \n"; } #
    try it yourselves at http://lezar.org/index2.cgi?whatever
      Hi Chady. You are having some trouble, and I can't give you a straight, simple, do-one-thing answer (I don't think anybody could). However, if you go back and read all the informative and straightforward replies you got all day from the other monks here, you could probably get a handle on your situation.

      Here are my own thoughts on your problem:

      1. Enable warnings by putting a -w after 'perl' on the first line. Like so:
        #!/usr/bin/perl # no warnings #!/usr/bin/perl -w # warnings enabled
        This will give you debugging information that will be output into your Error_Log for Apache, or IIS, or whatever you're using. As it stands, your code is VALID (as far as I can see), it just doesn't do what you want it to. Turning warnings on won't fix this problem directly, but it might help you understand what's going on a little better.

      2. Simplify your code by removing the HTML and tertiary functionality. This will help you narrow down where the problem is. For example:
        #!/usr/bin/perl -w @all = split(/?/,$ENV{'HTTP_REFERER'}); $where = @all[1]; die $where;
        Just running that snippet and checking the Error_Log will let you determine if your split is running properly, if you're using the correct environment variable, if you're making your array call correctly, et cetera. Based on the output value of $where you can figure out where your (first) problem is.

      3. Environment variables are tricky. Some are only defined under certain circumstances. For example, QUERY_STRING will only be defined if there is a question mark at the end of the URL path. For example:
        A) http://www.host.com/cgi-bin/test-script.pl B) http://www.host.com/cgi-bin/test-script.pl?param=value C) http://www.host.com/cgi-bin/test-script.pl?param=value&color=blue 1: #!/usr/bin/perl -w 2: 3: warn $ENV{'QUERY_STRING'}; Line 3 returns: A) blank (null string, no data) B) param=value C) param=value&color=blue
        Keep this in mind.

      4. CGI.pm is great for dealing with different parameter values. I know you're a newbie, but it's really easy and intuitive. Here's some quick code for you:
        #!/usr/bin/perl -w use CGI; use strict; my $cgi = new CGI; # this creates a new CGI object my $where = $cgi->param('where'); warn $where;
        Now you can call this script like this: /cgi-bin/locator.pl?where=Front And 'Front' will be written to your Error_Log. Simple, right?

      Mostly I've just echoed what's already been written in reply to your first post. There's not much more we can give you.

      Good luck.

      'kaboo

      PS - If you're having all this trouble trying to do this in Perl, you're going to have a seizure trying to do it in JavaScript. 'nuff said.

        well.. it seems that the server is f**ing with me... I don't know what is going on...
        I tried to debug the code by using this code
        foreach $key (sort(keys %ENV)) { print "$key = $ENV{$key}<br>\n"; }
        so I got this output:
        DOCUMENT_ROOT = /data1/virtualave.net/lezar GATEWAY_INTERFACE = CGI/1.1 HTTP_ACCEPT = */* HTTP_ACCEPT_ENCODING = gzip, deflate HTTP_ACCEPT_LANGUAGE = en-us HTTP_CACHE_CONTROL = max-stale=0 HTTP_COOKIE = p_go2id=UE5dCG1Pd76kk/ZxDmBBgw HTTP_HOST = lezar.virtualave.net HTTP_REFERER = http://lezar.org/index2.cgi?Front HTTP_USER_AGENT = Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigEx +t) PATH = /usr/local/bin:/usr/bin:/bin QUERY_STRING = REMOTE_ADDR = 209.239.68.247 REMOTE_PORT = 34052 REQUEST_METHOD = GET REQUEST_URI = /index2.cgi SCRIPT_FILENAME = /data1/va/lezar/index2.cgi SCRIPT_NAME = /index2.cgi SCRIPT_URI = http://lezar.virtualave.net/index2.cgi SCRIPT_URL = /index2.cgi SERVER_ADMIN = webmaster@virtualave.net SERVER_NAME = lezar.virtualave.net SERVER_PORT = 80 SERVER_PROTOCOL = HTTP/1.0 SERVER_SOFTWARE = Apache/1.3.6 (Unix)
        as you can see, the QUERY_STRING appears blank... I don't know what is really going on, it seems like something is wrong with Virtual Avenue
        so before I go on and work on simplifying the code, I have to see what the heck is going on with the server, and their customer support is not quite satisfying

        STILL STUCK
        Chady
        http://chady.net