Re: Perfecting index.pl some more!



Also sprach Nikos:

> Here is how my script has been transformed thanks to your precious
> precious suggestions and mine's minor alternation:
>
> #!/usr/bin/perl
> use strict;
> use warnings;
> use CGI::Carp qw(fatalsToBrowser);
> use CGI qw(:standard);
> use CGI::Cookie;
> use DBD::mysql;

I think you can drop that line as DBI will pull in the appropriate
database driver for you.

> use DBI;
> use POSIX qw(strftime);
>
> print header( -charset=>'iso-8859-7' );
> print start_html( -style=>'../data/css/style.css', -title=>'Øõ÷ùöåëÞ Ð
> +íåõìáôéêÜ Êåßìåíá!', -background=>'../data/images/night.gif' );
>
> my ($sth, $row);
> my $date = strftime( "%d %b, %H:%M", localtime );
> my $host = $ENV{'REMOTE_HOST'};
> $host = "Íßêïò" if ( ($host eq "dell") or ($host eq "localhost") or ($
> +host ~= /vivodi.gr/) );
>
> my $dbh = ($ENV{'SERVER_NAME'} ne 'nikolas.50free.net')
> ? DBI->connect('DBI:mysql:nikos_db', 'root', 'c
> +ensored')
> : DBI->connect('DBI:mysql:nikos_db:50free.net', 'nikos_db', 'c
> +ensored')
> or {RaiseError=>1};

[ You should do something against long lines in your postings;
These continuation pluses make the code hard to read in a newsreader. ]

> #*********************************************************************
> +**********
>
> my @files = <../data/text/*.txt>;
> my @display_files = map( /([^\/]+)\.txt/, @files );
>
> print start_form(-action=>'index.pl');
> print p( {-align=>'center'}, font( {-size=>5, -color=>'Lime'}, '
> +ÄéÜëåîå Ýíá áðü ôá êåßìåíá ãéá íá äéáâÜóåéò => ' ),
> popup_menu( -name=>'select', -value
> +s=>\@display_files ),
> submit('ÅðéëïãÞ'));
> print end_form(), br();
>
> my %sql = (
> get_counter => "SELECT counter FROM visitorlog",
> get_host => "SELECT host FROM visitorlog WHERE host=?",
> update_visitor => "UPDATE visitorlog SET counter+=1 WHERE host=?",
> update_passage => "UPDATE visitorlog SET passage=? WHERE host=?",
> insert_host => "INSERT INTO visitorlog (null, host, date, passa
> +ge, counter) VALUES (?, ?, ?, ?, ?, ?)"
> );
>
> my $passage = param('select') || "Áñ÷éêÞ Óåëßäá!";
> my ($data, @data);

@data should be declared in the smallest possible scope. So remove its
declaration.

> if (param('select') and param('select') != '..')

The second conditions is most likely always true because you use the
wrong comparison-operator. String comparison is done with 'eq' and
'ne'.

> {
> open(FILE, "<../data/text/$passage.txt") or die $!;
> @data = <FILE>;

my @data = <FILE>;

> close(FILE);
>
> $data = join('', @data);

No need to read the file linewise and then join the lines to one string.
Instead:

local $/; # enable slurp-mode
$data = <FILE>;

See $INPUT_RECORD_SEPARATOR in 'perldoc perlvar'.

> $sth = $dbh->prepare( $sql{update_passage} );
> $sth->execute($passage, $host);
> }
> else
> {

[...]

> }
>
> $data =~ s/\n/\\n/g;
> $data =~ s/"/\\"/g;
> $data =~ tr/\cM//d;

As you want shorter code, here's one way:

s/\n/\\n/g,
s/"/\\"/g ,
tr/\cM//d ,
for $data;

> #*********************************************************************
> +**********
> print <<ENDOFHTML;

[...]

> ENDOFHTML
> #*********************************************************************
> +**********
>
> print br(), br(), br();

More concise:

print br() x 3;

> print start_form(-action=>'show.pl');
> print table( {class=>'user'},
> Tr( td( 'Ðþò óå ëÝíå áäåëöå?'
> + ), td( textfield( 'name' ))),
> Tr( td( 'ÐïéÜ åßíáé ç ãíþìç óïõ ãéá ôçí åõ÷ïýëá
> »Êýñéå Éçóïý ×ñéóôÝ, ÅëÝçóïí Ìå« ?'
> + ), td( textarea( -name=>'pray', -rows=>4, -columns=>25 ))),
> Tr( td( 'ÐåñéÝãñáøå ìáò ìéá ðñïóùðéêÞ óïõ
> ðíåõìáôéêÞ åìðåéñßá áðü êÜðïéïí ãÝñïíôá ðñïò
> þöåëïò ôùí õðïëïßðùí áäåëöþí ( áí öõóéêÜ Ý÷åéò :-)'
> + ), td( textarea( -name=>'remark', -rows=>6, -columns=>25 ))),
> Tr( td( 'Ðïéü åßíáé ôï email óïõ?'
> + ), td( textfield( 'email' ))),
> Tr( td( submit( 'ÅìöÜíéóç üëùí ôùí áðüøåùí'
> + )), td( submit( 'ÁðïóôïëÞ' ))),
> );
> print end_form(), br(), br();
>
> open(FILE, "<../data/text/tips") or die $!;
> my @tips = <FILE>;
> close(FILE);
>
> @tips = grep { !/^\s*\z/s } @tips;

No need for the /s modifier (it only affects what '.' matches). Also,
but this is probably a matter of style, either write '/^\s*$/' or
'/\A\s*\z' for consistency. Better yet, avoid \A and \z altogether. They
are fairly uncommon (incidentally, I had to look up their meaning
first).

> my $tip = $tips[ int(rand(@tips)) ];

The int() is reduntant here. Array-subscripts can only be integers, so
perl will truncate the number for you:

my $tip = $tips[ rand @tips ];

> print table( {class=>'tip'}, Tr( td( {class=>'tip'}, $tip ))), br();
>
> $sth = $dbh->prepare( $sql{update_counter} ) if ($host ne "Íßêïò");
> $sth->execute;
>
> $sth = $dbh->prepare( $sql{get_counter} );
> $sth->execute;
>
> #here i decided to add together all the times visitors visit
> #my webpage so to get a total counter in order to avoid
> #create a new mysql table called counters and store that
> #value there. Or even to a flat file!
> while ($row = $sth->fetchrow_hashref)
> {
> $counter += $row->{counter};
> }

A flat file for a counter might in fact be a better idea than iterating
over an SQL-table. It should be less wasteful. In case you should use a
file, be aware of locking issues that have to be taken into account.

> print table( {class=>'info'},
> Tr( td( {class=>'host'}, $host )),
> Tr( td( {class=>'date'}, $date )),
> Tr( td( {class=>'counter'}, $counter ))
> );
>
> print br(), a( {href=>'games.pl'}, img{src=>'../data/
> +images/games.gif'} );
> print p( {-align=>'right'}, a( {href=>'show.pl?name=showlog'}, font(
> + {-size=>2, -color=>'Lime'}, b( 'Last Update: 30/4/2005' ))));
>
>
> How i can i shorter it, perfect it some more by dividing into subs?
> What must be/not be in a sub?

For a script of that length, functions are probably not required. The
logic is fairly linear and you're not jumping around in it too much.

Tassilo
--
use bigint;
$n=71423350343770280161397026330337371139054411854220053437565440;
$m=-8,;;$_=$n&(0xff)<<$m,,$_>>=$m,,print+chr,,while(($m+=8)<=200);
.



Relevant Pages

  • encoding pragma aborts script
    ... I have an app which connects via DBI:DBD:CSV to a flat file. ... When I include pragma use encoding, the app aborts (message from OS and the ... I found out that script is aborted during execute method of DBI. ...
    (perl.dbi.users)
  • newbie question: the steps of a making a ping service
    ... I want to store a list of web addresses in a flat file, and then, once ... into an array, then loop though that array and open the pages. ... need to use this service from several servers. ... So I'm asking what are the steps involved in making this script? ...
    (comp.lang.java)
  • Re: Printing a directory tree
    ... Kevin Rodgers wrote: ... >> This works by executing the script from any directory. ... >> But say I have a flat file that has a tree structure of the ...
    (comp.unix.shell)
  • Re: newbie question: the steps of a making a ping service
    ... >> I want to store a list of web addresses in a flat file, and then, once ... >> cron, but I think doing this in Java would be more portable, and I ... >> need to use this service from several servers. ... >> So I'm asking what are the steps involved in making this script? ...
    (comp.lang.java)