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

Hi,
First a quick explanation of my problem, then an explanation of what the script is actually doing.

When I point my browser (NN 6 mac) at the script, without sending input, it displays what it's supposed to (incuding the closing HTML tags), but never finishes loading.
The status says "Document: Done", but the progress bar is only half-way across, and the animated "N" continues to animate (forever).

So, to put it simply, is there something wrong with my script, or is it just a silly browser bug?

I've tested the script with my usual array of browsers, namely
mac - IE 4.0, 4.5, 5.0, 5.02, 5.1 - NN 4.75, 4.76, 6 - Opera 5.0
p.c. - IE 5.0, 6.0 - Opera 6.01
And the only one that doesn't seem to finish loading properly is NN 6 on mac.

Reason: my host is making changes to all accounts, including changing email username changes and directory structure changes amongst others.
This script ftp's into every site I manage to see if the directory structure has changed, so that when it does, I can upload revised versions of all scripts and then phone my customers to help them change their outlook express settings.
I have this script displayed in a browser in the background continually, and frequently hit 'refresh' and see if anything's different.

The script checks that it's running under a secure server, if not it prints an error.
When the script is called without input, it prints a table of all the websites defined in @sites and an adjascent password box so that I can enter the passwords for the sites I want to check. When the passwords are submitted to the script, it ftp's into each server and prints me a page showing, for each site, particular files in particular folders.

The script works in all respects other than the initial page doesn't seem to finish loading properly. I'm currently using the script with no 'apparant' problems, but I'd just like to know whether I'm exiting the script properly (Would it be possible for me to exit improperly? :)).
Is the 'finish' sub I'm using bad practise?

And of course, I welcome and comments/criticisms about the security and implementation of my coding.

Thanks a lot,
fireartist
#!/usr/bin/perl -wT use strict; use CGI; use Net::FTP; my $q = new CGI; print $q->header, $q->start_html; # Disable uploads $CGI::DISABLE_UPLOADS = 1; # Maximum number of bytes per post $CGI::POST_MAX = 1; #comment out the next line when live #use CGI::Carp qw(fatalsToBrowser); # ###Fill usernames and passwords my @sites = ("site1.com", "site2.com", "site3.com"); my %username = ( "site1com" => "usernam1", "site2com" => "usernam2", "site3com" => "usernam3"); # ###Start program my ($ftp, $error, $site, %password); &Hashes; #check this is running on a secure server unless ( $q->https() ) { print $q->center('NOT secure'); &finish; } #have the passwords been sent? if ( $q->param('pass') ) { &sortPasswords; &mainStuff; } else { &askForPasswords; } &finish; exit 0; # ### sub mainStuff { foreach $site (@sites) { #format site name for use with hashes $_ = $site; $_ =~ s/-//g; $_ =~ s/\.//g; my $username = $username{$_}; if ( $q->param("$username") ) { my $password = $password{$username}; print "<br><b>$site</b><br> \n"; #create new ftp object $ftp = Net::FTP->new("$site", Debug => 0); #login to ftp $ftp->login("$username", "$password") or &pushError("ftp login error with $site"); #get dir listing my @dir1 = $ftp->dir() or &pushError("ftp error with dir on $site"); #print out the dir listing print "/home/"."$username"."/<br>"; my $line1; foreach $line1 (@dir1) { if ($line1 =~ /www|htdocs|cgi-bin/) { print "$line1<br>"; } } print "/home/"."$username"."/www/<br>"; #get dir listing my @dir2 = $ftp->dir('www') or &pushError("ftp error with dir on $site"); #print out the dir listing my $line2; foreach $line2 (@dir2) { if ($line2 =~ /htdocs|cgi-bin/) { print "$line2<br>"; } } #disconnect from ftp $ftp->quit or &pushError("error disconnecting from $site"); } } } sub sortPasswords { foreach $site (@sites) { my $password; #format site name for use with hashes $_ = $site; $_ =~ s/-//g; $_ =~ s/\.//g; my $username = $username{$_}; #check if password was sent if ( $q->param("$username") ) { $password = $q->param("$username"); unless ( $password =~ /^[\w]*$/ ) { print "<b>Illegal password entered for $site</b>"; &finish; } $password{$username} = $password; } } } sub askForPasswords { #get this scripts url my $url = $q->url(-absolute=>1); #start form print "<table align=\"center\">"; print $q->start_form(-method=>"POST", -action=>"$url"); print $q->hidden(-name=>'pass', -default=>1); #print password boxes foreach $site (@sites) { #format site name for use with hashes $_ = $site; $_ =~ s/-//g; $_ =~ s/\.//g; my $username = $username{$_}; print "<tr><td>"."$site"."</td><td>"; print $q->password_field(-name=>"$username", -value=>'', -size=>8); print "</td><tr>"; } #print submit and reset buttons print "<tr><td>"; print $q->submit; print "</td><td>"; print $q->reset; print "</td></tr>"; #end form print $q->endform; print "</table>"; } sub checkHashes { foreach $site ( @sites ) { $_ = $site; $_ =~ s/-//g; $_ =~ s/\.//g; unless ( defined ($username{$_}) ) { print "error with username hash at $site <br> \n"; $error = 1; } } if ( defined ($error) ) { &finish } } sub pushError { print "<br><b>$_[0]</b><br> \n"; } sub finish { print $q->end_html; exit 0; }

2002-03-06 - Edited by dvergin to fix ampersands per user request

Replies are listed 'Best First'.
Re: Exiting improperly, or NN6 error?
by dash2 (Hermit) on Mar 06, 2002 at 13:01 UTC
    If it works fine on everything but Mac NN6, and it works fine on Mac NN6 (but the Mac NN6 loading bar and spinner keep going), then it probably works fine.

    Regarding your code:

    This bit is silly:

    #format site name for use with hashes $_ = $site; $_ =~ s/-//g; $_ =~ s/\.//g; my $username = $username{$_};

    You don't need to get rid of characters like this to use hashes. You just need to put the hash key in quotes, if you are using it raw. E.g.

    my %username = ( "site1.com" => "usernam1", "site2.com" => "usernam2", "site3.com" => "usernam3");

    On a similar note, name => "$username" can just be  name => $username. You don't need to force string context, Perl does that for you automatically. Ditto elsewhere in the script.

    Personally, I also think that using CGI just to print HTML results in an ugly mix of HTML and perl; but that is my idiosyncratic view.

    Other than that... hmm. "finish". On the whole, I suspect it is good to have a single "normal" exit point for a script - which would be in the main body, not a subroutine - and a separate "error" exit. Initially, these may do the same things. But sooner or later you may want to e.g. log an error to a file or whatever, and "finish" won't let you do that because it doesn't distinguish between good and bad exits. But that is just my opinion, again.

    dave hj~

      Quote:
      "If it works fine on everything but Mac NN6, and it works fine on Mac NN6 (but the Mac NN6 loading bar and spinner keep going), then it probably works fine."
      -Wise words indeed! :)
      I just wasn't sure, as it's the first time I've viewed a page which hasn't 'finished' eventually.

      Regarding the silly bit,
      I remember needing to do it, but why escapes me now. Yes, I can see that it is silly, I will sort it out.
      Thanks too, for the tip on quoting variables.
      Re: CGI - I find it more reliable to use CGI for headers, start_html etc.
      (Read: -it's easier to remember how to spell "header" than "Content-type: text/html\n\n")

      Thank you very much for your input on my code.
      Regarding the NN6 thing, I guess it might remain a mystery.
      Oh well, one more mystery in life won't hurt :)

      fireartist
Re: Exiting improperly, or NN6 error?
by converter (Priest) on Mar 06, 2002 at 14:12 UTC

    Navigator 6 is Beta code and still has a lot of problems. Before spending too much time agonizing over your code, you should probably pay a visit to http://bugzilla.mozilla.org/ and do a few searches to see if there are bugs that might explain the problem.

    For what it's worth, you ought to try mozilla nightly builds as well as the commercial build. The nightly builds are pretty solid now, and a lot of bugs have been fixed since NN6.

      <opinion>I find the Mozilla browser (I'm on 0.9.8 now) much better than the Netscape6 I downloaded a while ago.</opinion>

      ..Guv

      Thanks converter and guvnor,
      I didn't know that NN6 was considered Beta.
      I'll certainly look into updating it a.s.a.p., I'll also look into mozilla again.
      I've stayed clear off it for a while, as my only experience with it was with the version that came with RedHat 7.2 that I installed on my home machine. - v.buggy :)
Re: Exiting improperly, or NN6 error?
by joealba (Hermit) on Mar 06, 2002 at 13:11 UTC
    If you were somehow keeping a connection open and continually sending new data to the browser, you'd see the same problem across most/all the other browsers you've tested (until they time out after 2 or 5 minutes). The script shouldn't care if you're accessing it from NN6, IE, Opera, or Lynx.. It'll just do what it needs to do and exit. So, I'd chalk it up to a Netscape bug. I'll give it a quick test run and update this post when I get to work in an hour...

    BUT, $CGI::POST_MAX = 1; ??? You're taking in 'username' and 'password' as params. You probably need a little more than 1 byte to pull these in. Or, am I misunderstanding your usage of this?? You're not passing a username and password through GET, are you?

    $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.
      I thought that
      $CGI::POST_MAX = 1;
      only affected file uploads.

      The text you quoted implies that this isn't so, so in that case I don't know why the script is working when I POST to it.
Re: Exiting improperly, or NN6 error?
by hakkr (Chaplain) on Mar 06, 2002 at 13:13 UTC
    Check all your table tags match up. Netscape does not display anything until all the tables have been created properly
      The table seems o.k.
      I saved the final (displayed) page as HTML and opened it in dreamweaver. It didn't scream 'errors' at me as it usually would.
      Thanks tho.
Re: Exiting improperly, or NN6 error?
by thraxil (Prior) on Mar 06, 2002 at 17:22 UTC

    i remember there being bugs in a few mozilla milestones (and the Netscape versions that were built on them) where if the form was a multipart, and you submitted it without actually selecting a file for upload (or selecting a nonexistant file), it would never close the connection properly and just hang like you describe. i don't think CGI creates form tags with enctype="multipart/form-data" unless you explicitly tell it to though. so it's probably not the same bug, but may be related.

    anders pearson

Re: Exiting improperly, or NN6 error?
by fireartist (Chaplain) on Mar 06, 2002 at 12:22 UTC
    p.s. Sorry about the "&" problem there in the code, I didn't notice that in the preview :(