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

my $script = param('select') or "Αρχική Σελίδα!"; $sth = $dbh->prepare( "SELECT host FROM guestlog" ); $sth->execute(); while( $row = $sth->fetchrow_hashref ) { if( $host eq $row->{host} ) { my $hostmatch = 1; } } if( param('select') and param('select') !~ /\.\./ ) { open(FILE, "<../data/text/$script.txt") or die $!; my @data = <FILE>; close(FILE); my $data = join('', @data); $dbh->do( "UPDATE guestlog SET script='$script' WHERE host='$host' +" ) or die $dbh->errstr; } elsif( $hostmatch == 1 ) { $dbh->do( "UPDATE guestlog SET hostcount = hostcount + 1 WHERE hos +t='$host'" ) or die $dbh->errstr; $sth = $dbh->prepare( "SELECT * FROM guestlog WHERE host='$host'" +); $sth->execute(); $row = $sth->fetchrow_hashref; $data = "Καλώς ήλθες " .$host. "! Χαίρομαι που βρίσκες την σελίδα +ενδιαφέρουσα!\n" . "Τελευταία φορά ήρθες εδώ ως " .$row->{host}. " στις " .$r +ow->{date}. " !!\n" . "Σύνολικές ήρθες εδώ " .$row->{hostcount}. " φορές!!!\n" . "Τελευταία είδες το κείμενο { " .$row->{script}. " }\n" . "Ποιό κείμενο θα μελετήσεςι αυτήν την φορά !?"; } elsif( $hostmatch != 1 ) { if ( $host ne "Νίκος" ) { $data = "Γειά σου " .$host. "!\n" . "Έρχεσαι για 1η φορά εδώ !!\n" . "Ελπίζω να βρείς τα κείμενα ενδιαφέροντα :-)"; $dbh->do( "INSERT INTO guestlog VALUES (null, '$host', '$date', + '$script', 1, 1)" ) or die $dbh->errstr; } else { $data = "Γειά σου Νικόλα, τι χαμπάρια?! Όλα δεξιά να σου πάνε π +άντα! ;-)"; } }
ok with the above script iam trying to see if the current hostname of a visitor exists in guestlog mysql database. If it does then i just update the existing record, if it does not i just welcome the user. Please you asked me to ask specific questions and here i ask one: Is the above logic correct? Is there any betetr that i can write it? ps. Sorry about the Greek folks but although i use UTF-8 it still being displayed like shit. I hate seeing it myself too but i donw know how can they be displayed correctly.

Replies are listed 'Best First'.
Re: Is this logic correct? Maybe can be rewritten better?
by dragonchild (Archbishop) on Apr 29, 2005 at 15:09 UTC
    This is much better, Nik. You need to learn about placeholders, but your code and your question are better then previous efforts.

    However, you are not using strict or, if you are, you are neutering it by having a huge my() or use vars() at the top. Had you been using strict, the bug trammell noticed would have been noticed for you by perl itself. That's why we have been telling you over and over to use it. Warnings would also help find other bugs you have.

    As for your UTF-8, the better thing to do would be to create a sample script that only uses ASCII and demonstrates the question you have. Post that, then take the answers given and apply them to your real script.

    As for your logic - I don't know what $data does. I also don't know why you're checking the 'select' parameter from your form before caring if the $hostmatch variable is 1 or not 1. Your specifications are unclear.


    The Perfect is the Enemy of the Good.

      Thank you Dragonchild. I srted to use strict and warnigns as matter of fact that iam using it at this script i posted. Here si thw whole script:

      I decided not to use html::Template although in another post i posted to you how i have done it. It gives me a headache. i will just use cgi.pm as i used too and css as well to help me lessen print formatting inside my perl cgi scripts.

      Iam getting this errors too although i ahve set all my vars with my:
      Global symbol "$hostmatch" requires explicit package name at D:\www\cg +i-bin\index.pl line 61. Global symbol "$data" requires explicit package name at D:\www\cgi-bin +\index.pl line 68. Global symbol "$hostmatch" requires explicit package name at D:\www\cg +i-bin\index.pl line 74. Global symbol "$data" requires explicit package name at D:\www\cgi-bin +\index.pl line 78. Global symbol "$data" requires explicit package name at D:\www\cgi-bin +\index.pl line 86. Global symbol "$data" requires explicit package name at D:\www\cgi-bin +\index.pl line 90. Global symbol "$data" requires explicit package name at D:\www\cgi-bin +\index.pl line 91. Global symbol "$data" requires explicit package name at D:\www\cgi-bin +\index.pl line 92. Global symbol "$data" requires explicit package name at D:\www\cgi-bin +\index.pl line 95. Execution of D:\www\cgi-bin\index.pl aborted due to compilation errors +.
      Please help me rebuild this index.pl in a better more straightforwardway and please point out to me my errors. Thank you.

        When you use my $hostmatch inside the if, you're creating a variable that only exists within the if. Any value you assign to it will disappear along with the variable once outside the if. That means elsif( $hostmatch == 1 ) is using a variable that no longer exists. The solution is:

        my $hostmatch; while( $row = $sth->fetchrow_hashref ) { if( $host eq $row->{host} ) { $hostmatch = 1; } }

        Same goes for $data. Change

        if( param('select') and param('select') !~ /\.\./ ) { my $data = ... ... }

        to

        my $data; if( param('select') and param('select') !~ /\.\./ ) { $data = ... ... }
        A reply falls below the community's threshold of quality. You may see it by logging in.

        Don't roll your own localtime-to-string routine. Use POSIX and strftime, which aside from requiring no extraneous months array and being less code will also respect the date formatting conventions of the current locate.

Re: Is this logic correct? Maybe can be rewritten better?
by ikegami (Patriarch) on Apr 29, 2005 at 15:14 UTC

    Your vulnerable to SQL injection attacks. For example, $script is not validated in

    my $script = param('select') or ...; ... $dbh->do("UPDATE guestlog SET script='$script' WHERE host='$host'");

    Escape special characters within $script (and $host and $date) using $dbh->quote, or better yet, bind the arguments as shown here:

    my $script = param('select') or ...; ... $dbh->do("UPDATE guestlog SET script=? WHERE host=?", undef, $script, +$host);

    The same applies to prepare. For example,

    $sth = $dbh->prepare( "SELECT * FROM guestlog WHERE host='$host'"); $sth->execute();

    becomes

    $sth = $dbh->prepare("SELECT * FROM guestlog WHERE host=?"); $sth->execute($host);

    By the way, this site uses iso-latin-1 (ISO-8859-1), not UTF-8. You'll have to use HTML entities such as &#xxxx; if you want to display characters outside of iso-latin-1. Unfortunately, those won't work within <code> tags.

    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: Is this logic correct? Maybe can be rewritten better?
by trammell (Priest) on Apr 29, 2005 at 15:00 UTC
    while( $row = $sth->fetchrow_hashref ) { if( $host eq $row->{host} ) { my $hostmatch = 1; } }
    This doesn't make a lot of sense; you probably want to scope $hostmatch outside the while loop.
      That means the you, the OP, probably aren't using use strict. If you had, elsif( $hostmatch == 1 ) would have resulted in an error unless you declared $hostmatch twice. Please use use strict; use warnings; and address any resulting errors and warnings.
      A reply falls below the community's threshold of quality. You may see it by logging in.